/*
 * Copyright 2011-2024 Branimir Karadzic. All rights reserved.
 * License: https://github.com/bkaradzic/bgfx/blob/master/LICENSE
 */

#include "common.h"
#include "bgfx_utils.h"
#include "imgui/imgui.h"
#include <map>
#pragma region font
#include <bx/timer.h>
#include <bx/string.h>
#include <bx/math.h>

#include "font/font_manager.h"
#include "font/text_buffer_manager.h"
#include "entry/input.h"

#include <iconfontheaders/icons_font_awesome.h>
#include <iconfontheaders/icons_kenney.h>

#include <wchar.h>
#pragma endregion
#pragma region font_sdf
#include "font/text_metrics.h"
#pragma endregion
#pragma region picking
#include <bx/rng.h>
#define RENDER_PASS_SHADING 0  // Default forward rendered geo with simple shading
#define RENDER_PASS_ID      1  // ID buffer for picking
#define RENDER_PASS_BLIT    2  // Blit GPU render target to CPU texture

#define ID_DIM 8  // Size of the ID buffer
#pragma endregion
#pragma region 29-debugdraw
#include <entry/cmd.h>
#include <entry/input.h>
#include <debugdraw/debugdraw.h>
#include "camera.h"
#include "imgui/imgui.h"

#include <bx/uint32_t.h>
#pragma endregion

namespace
{
	struct DrawMode{
		enum{
			WireframeShaded,
			Wireframe,
			Shaded,
		};
	};
	enum ExampleType {
		_01_Cubes,
		_04_Mesh,
		_05_Instancing,
		_10_Font,
		_11_Font_sdf,//scale in imgui
		_30_Picking,
		_29_Debugdraw,
		_28_Wireframe,
		_19_Oit,
	};
	static ExampleType m_current_example_type = ExampleType::_19_Oit;

#pragma region _10_Font
	TrueTypeHandle loadTtf(FontManager* _fm, const char* _filePath)
	{
		uint32_t size;
		void* data = load(_filePath, &size);

		if (NULL != data)
		{
			TrueTypeHandle handle = _fm->createTtf((uint8_t*)data, size);
			bx::free(entry::getAllocator(), data);
			return handle;
		}

		TrueTypeHandle invalid = BGFX_INVALID_HANDLE;
		return invalid;
	}

	static const char* s_fontFilePath[] =
	{
		"font/droidsans.ttf",
		"font/chp-fire.ttf",
		"font/bleeding_cowboys.ttf",
		"font/mias_scribblings.ttf",
		"font/ruritania.ttf",
		"font/signika-regular.ttf",
		"font/five_minutes.otf",
	};
#pragma endregion
#pragma region 29-debugdraw
	static DdVertex s_bunnyVertices[] =
	{
		{   25.0883f,  -44.2788f,   31.0055f },
		{  0.945623f,   53.5504f,  -24.6146f },
		{  -0.94455f,  -14.3443f,  -16.8223f },
		{  -20.1103f,  -48.6664f,   12.6763f },
		{  -1.60652f,  -26.3165f,  -24.5424f },
		{  -30.6284f,  -53.6299f,   14.7666f },
		{   1.69145f,  -43.8075f,  -15.2065f },
		{  -20.5139f,   21.0521f,  -5.40868f },
		{  -13.9518f,   53.6299f,  -39.1193f },
		{  -21.7912f,   48.7801f,  -42.0995f },
		{  -26.8408f,   23.6537f,  -17.7324f },
		{  -23.1196f,   33.9692f,   4.91483f },
		{  -12.3236f,  -41.6303f,   31.8324f },
		{   27.6427f,  -5.05034f,  -11.3201f },
		{   32.2565f,   1.30521f,   30.2671f },
		{   47.2723f,  -27.0974f,   11.1774f },
		{    33.598f,   10.5888f,   7.95916f },
		{  -13.2898f,   12.6234f,   5.55953f },
		{  -32.7364f,   19.0648f,  -10.5736f },
		{  -32.7536f,   31.4158f,  -1.40712f },
		{  -25.3672f,   30.2874f,  -12.4682f },
		{    32.921f,  -36.8408f,  -12.0254f },
		{  -37.7251f,  -33.8989f,  0.378443f },
		{  -35.6341f, -0.246891f,  -9.25165f },
		{  -16.7041f,  -50.0254f,  -15.6177f },
		{   24.6604f,  -53.5319f,  -11.1059f },
		{  -7.77574f,  -53.5719f,  -16.6655f },
		{   20.6241f,   13.3489f,  0.376349f },
		{  -44.2889f,   29.5222f,   18.7918f },
		{   18.5805f,   16.3651f,   12.6351f },
		{  -23.7853f,   31.7598f,  -6.54093f },
		{   24.7518f,  -53.5075f,   2.14984f },
		{  -45.7912f,  -17.6301f,   21.1198f },
		{   51.8403f,  -33.1847f,   24.3337f },
		{  -47.5343f,  -4.32792f,   4.06232f },
		{  -50.6832f,   -12.442f,   11.0994f },
		{  -49.5132f,   19.2782f,   3.17559f },
		{  -39.4881f,   29.0208f,  -6.70431f },
		{  -52.7286f,   1.23232f,   9.74872f },
		{    26.505f,  -16.1297f,  -17.0487f },
		{   -25.367f,   20.0473f,  -8.44282f },
		{  -24.5797f,  -10.3143f,  -18.3154f },
		{  -28.6707f,   6.12074f,   27.8025f },
		{  -16.9868f,   22.6819f,   1.37408f },
		{  -37.2678f,   23.9443f,   -9.4945f },
		{  -24.8562f,   21.3763f,   18.8847f },
		{  -47.1879f,    3.8542f,  -4.74621f },
		{   38.0706f,  -7.33673f,   -7.6099f },
		{  -34.8833f,  -3.57074f,   26.4838f },
		{   12.3797f,   5.46782f,   32.9762f },
		{  -31.5974f,   -22.956f,   30.5827f },
		{  -6.80953f,    48.055f,  -18.5116f },
		{    6.3474f,  -15.1622f,  -24.4726f },
		{  -25.5733f,   25.2452f,  -34.4736f },
		{  -23.8955f,   31.8323f,  -40.8696f },
		{  -11.8622f,   38.2304f,  -43.3125f },
		{  -20.4918f,   41.2409f,  -3.11271f },
		{   24.9806f,  -8.53455f,   37.2862f },
		{  -52.8935f,    5.3376f,    28.246f },
		{    34.106f,  -41.7941f,    30.962f },
		{  -1.26914f,   35.6664f,  -18.7177f },
		{  -0.13048f,   44.7288f,  -28.7163f },
		{   2.47929f,  0.678165f,  -14.6892f },
		{  -31.8649f,  -14.2299f,   32.2998f },
		{   -19.774f,   30.8258f,   5.77293f },
		{   49.8059f,   -37.125f,   4.97284f },
		{  -28.0581f,   -26.439f,  -14.8316f },
		{  -9.12066f,  -27.3987f,  -12.8592f },
		{  -13.8752f,  -29.9821f,   32.5962f },
		{   -6.6222f,  -10.9884f,   33.5007f },
		{  -21.2664f,  -53.6089f,  -3.49195f },
		{ -0.628672f,   52.8093f,  -9.88088f },
		{   8.02417f,   51.8956f,  -21.5834f },
		{  -44.6547f,   11.9973f,   34.7897f },
		{  -7.55466f,   37.9035f, -0.574101f },
		{   52.8252f,  -27.1986f,   11.6429f },
		{ -0.934591f,   9.81861f,  0.512566f },
		{  -3.01043f,   5.70605f,   22.0954f },
		{  -34.6337f,   44.5964f,  -31.1713f },
		{  -26.9017f,   35.1991f,  -32.4307f },
		{   15.9884f,  -8.92223f,  -14.7411f },
		{  -22.8337f,   -43.458f,   26.7274f },
		{  -31.9864f,  -47.0243f,   9.36972f },
		{  -36.9436f,   24.1866f,   29.2521f },
		{  -26.5411f,   29.6549f,   21.2867f },
		{   33.7644f,  -24.1886f,  -13.8513f },
		{  -2.44749f,  -17.0148f,   41.6617f },
		{   -38.364f,  -13.9823f,  -12.5705f },
		{  -10.2972f,  -51.6584f,    38.935f },
		{   1.28109f,  -43.4943f,   36.6288f },
		{  -19.7784f,  -44.0413f,  -4.23994f },
		{   37.0944f,  -53.5479f,   27.6467f },
		{   24.9642f,  -37.1722f,   35.7038f },
		{   37.5851f,   5.64874f,   21.6702f },
		{  -17.4738f,  -53.5734f,   30.0664f },
		{  -8.93088f,   45.3429f,  -34.4441f },
		{  -17.7111f,   -6.5723f,   29.5162f },
		{   44.0059f,  -17.4408f,  -5.08686f },
		{  -46.2534f,  -22.6115f,  0.702059f },
		{   43.9321f,  -33.8575f,   4.31819f },
		{   41.6762f,  -7.37115f,   27.6798f },
		{   8.20276f,  -42.0948f,  -18.0893f },
		{   26.2678f,  -44.6777f,  -10.6835f },
		{    17.709f,   13.1542f,   25.1769f },
		{  -35.9897f,   3.92007f,   35.8198f },
		{  -23.9323f,  -37.3142f,  -2.39396f },
		{   5.19169f,   46.8851f,  -28.7587f },
		{  -37.3072f,  -35.0484f,   16.9719f },
		{   45.0639f,  -28.5255f,   22.3465f },
		{  -34.4175f,   35.5861f,  -21.7562f },
		{   9.32684f,  -12.6655f,    42.189f },
		{   1.00938f,  -31.7694f,   43.1914f },
		{  -45.4666f,  -3.71104f,   19.2248f },
		{  -28.7999f,  -50.8481f,   31.5232f },
		{   35.2212f,  -45.9047f,  0.199736f },
		{      40.3f,  -53.5889f,   7.47622f },
		{   29.0515f,    5.1074f,   -10.002f },
		{   13.4336f,   4.84341f,  -9.72327f },
		{   11.0617f,   -26.245f,  -24.9471f },
		{  -35.6056f,  -51.2531f,  0.436527f },
		{  -10.6863f,   34.7374f,  -36.7452f },
		{  -51.7652f,   27.4957f,   7.79363f },
		{  -50.1898f,    18.379f,   26.3763f },
		{  -49.6836f,  -1.32722f,   26.2828f },
		{   19.0363f,  -16.9114f,   41.8511f },
		{   32.7141f,   -21.501f,   36.0025f },
		{   12.5418f,  -28.4244f,   43.3125f },
		{  -19.5634f,   42.6328f,  -27.0687f },
		{  -16.1942f,   6.55011f,   19.4066f },
		{   46.9886f,  -18.8482f,   22.1332f },
		{   45.9697f,  -3.76781f,   4.10111f },
		{  -28.2912f,   51.3277f,  -35.1815f },
		{  -40.2796f,  -27.7518f,   22.8684f },
		{  -22.7984f,  -38.9977f,    22.158f },
		{   54.0614f,  -35.6096f,    12.694f },
		{   44.2064f,  -53.6029f,   18.8679f },
		{    19.789f,   -29.517f,  -19.6094f },
		{  -34.3769f,   34.8566f,   9.92517f },
		{  -23.7518f,  -45.0319f,   8.71282f },
		{  -12.7978f,   3.55087f,  -13.7108f },
		{  -54.0614f,   8.83831f,   8.91353f },
		{   16.2986f,  -53.5717f,    34.065f },
		{  -36.6243f,  -53.5079f,   24.6495f },
		{   16.5794f,  -48.5747f,   35.5681f },
		{  -32.3263f,   41.4526f,  -18.7388f },
		{  -18.8488f,   9.62627f,  -8.81052f },
		{   5.35849f,   36.3616f,  -12.9346f },
		{   6.19167f,    34.497f,   -17.965f },
	};

	static const uint16_t s_bunnyTriList[] =
	{
		 80,   2,  52,
		  0, 143,  92,
		 51,   1,  71,
		 96, 128,  77,
		 67,   2,  41,
		 85,  39,  52,
		 58, 123,  38,
		 99,  21, 114,
		 55,   9,  54,
		136, 102,  21,
		  3, 133,  81,
		101, 136,   4,
		  5,  82,   3,
		  6,  90,  24,
		  7,  40, 145,
		 33,  75, 134,
		 55,   8,   9,
		 10,  40,  20,
		 46, 140,  38,
		 74,  64,  11,
		 89,  88,  12,
		147,  60,   7,
		 47, 116,  13,
		 59, 129, 108,
		147,  72, 106,
		 33, 108,  75,
		100,  57,  14,
		129, 130,  15,
		 32,  35, 112,
		 16,  29,  27,
		107,  98, 132,
		130, 116,  47,
		 17,  43,   7,
		 54,  44,  53,
		 46,  34,  23,
		 87,  41,  23,
		 40,  10,  18,
		  8, 131,   9,
		 11,  19,  56,
		 11, 137,  19,
		 19,  20,  30,
		 28, 121, 137,
		122, 140,  36,
		 15, 130,  97,
		 28,  84,  83,
		114,  21, 102,
		 87,  98,  22,
		 41, 145,  23,
		133,  68,  12,
		 90,  70,  24,
		 31,  25,  26,
		 98,  34,  35,
		 16,  27, 116,
		 28,  83, 122,
		 29, 103,  77,
		 40,  30,  20,
		 14,  49, 103,
		 31,  26, 142,
		 78,   9, 131,
		 80,  62,   2,
		  6,  67, 105,
		 32,  48,  63,
		 60,  30,   7,
		 33, 135,  91,
		116, 130,  16,
		 47,  13,  39,
		 70, 119,   5,
		 24,  26,   6,
		102,  25,  31,
		103,  49,  77,
		 16, 130,  93,
		125, 126, 124,
		111,  86, 110,
		  4,  52,   2,
		 87,  34,  98,
		  4,   6, 101,
		 29,  76,  27,
		112,  35,  34,
		  6,   4,  67,
		 72,   1, 106,
		 26,  24,  70,
		 36,  37, 121,
		 81, 113, 142,
		 44, 109,  37,
		122,  58,  38,
		 96,  48, 128,
		 71,  11,  56,
		 73, 122,  83,
		 52,  39,  80,
		 40,  18, 145,
		 82,   5, 119,
		 10,  20, 120,
		139, 145,  41,
		  3, 142,   5,
		 76, 117,  27,
		 95, 120,  20,
		104,  45,  42,
		128,  43,  17,
		 44,  37,  36,
		128,  45,  64,
		143, 111, 126,
		 34,  46,  38,
		 97, 130,  47,
		142,  91, 115,
		114,  31, 115,
		125, 100, 129,
		 48,  96,  63,
		 62,  41,   2,
		 69,  77,  49,
		133,  50,  68,
		 60,  51,  30,
		  4, 118,  52,
		 53,  55,  54,
		 95,   8,  55,
		121,  37,  19,
		 65,  75,  99,
		 51,  56,  30,
		 14,  57, 110,
		 58, 122,  73,
		 59,  92, 125,
		 42,  45, 128,
		 49,  14, 110,
		 60, 147,  61,
		 76,  62, 117,
		 69,  49,  86,
		 26,   5, 142,
		 46,  44,  36,
		 63,  50, 132,
		128,  64,  43,
		 75, 108,  15,
		134,  75,  65,
		 68,  69,  86,
		 62,  76, 145,
		142, 141,  91,
		 67,  66, 105,
		 69,  68,  96,
		119,  70,  90,
		 33,  91, 108,
		136, 118,   4,
		 56,  51,  71,
		  1,  72,  71,
		 23,  18,  44,
		104, 123,  73,
		106,   1,  61,
		 86, 111,  68,
		 83,  45, 104,
		 30,  56,  19,
		 15,  97,  99,
		 71,  74,  11,
		 15,  99,  75,
		 25, 102,   6,
		 12,  94,  81,
		135,  33, 134,
		138, 133,   3,
		 76,  29,  77,
		 94,  88, 141,
		115,  31, 142,
		 36, 121, 122,
		  4,   2,  67,
		  9,  78,  79,
		137, 121,  19,
		 69,  96,  77,
		 13,  62,  80,
		  8, 127, 131,
		143, 141,  89,
		133,  12,  81,
		 82, 119, 138,
		 45,  83,  84,
		 21,  85, 136,
		126, 110, 124,
		 86,  49, 110,
		 13, 116, 117,
		 22,  66,  87,
		141,  88,  89,
		 64,  45,  84,
		 79,  78, 109,
		 26,  70,   5,
		 14,  93, 100,
		 68,  50,  63,
		 90, 105, 138,
		141,   0,  91,
		105,  90,   6,
		  0,  92,  59,
		 17, 145,  76,
		 29,  93, 103,
		113,  81,  94,
		 39,  85,  47,
		132,  35,  32,
		128,  48,  42,
		 93,  29,  16,
		145,  18,  23,
		108, 129,  15,
		 32, 112,  48,
		 66,  41,  87,
		120,  95,  55,
		 96,  68,  63,
		 85,  99,  97,
		 18,  53,  44,
		 22,  98, 107,
		 98,  35, 132,
		 95, 127,   8,
		137,  64,  84,
		 18,  10,  53,
		 21,  99,  85,
		 54,  79,  44,
		100,  93, 130,
		142,   3,  81,
		102, 101,   6,
		 93,  14, 103,
		 42,  48, 104,
		 87,  23,  34,
		 66,  22, 105,
		106,  61, 147,
		 72,  74,  71,
		109, 144,  37,
		115,  65,  99,
		107, 132, 133,
		 94,  12,  88,
		108,  91,  59,
		 43,  64,  74,
		109,  78, 144,
		 43, 147,   7,
		 91, 135, 115,
		111, 110, 126,
		 38, 112,  34,
		142, 113,  94,
		 54,   9,  79,
		120,  53,  10,
		138,   3,  82,
		114, 102,  31,
		134,  65, 115,
		105,  22, 107,
		125, 129,  59,
		 37, 144,  19,
		 17,  76,  77,
		 89,  12, 111,
		 41,  66,  67,
		 13, 117,  62,
		116,  27, 117,
		136,  52, 118,
		 51,  60,  61,
		138, 119,  90,
		 53, 120,  55,
		 68, 111,  12,
		122, 121,  28,
		123,  58,  73,
		110,  57, 124,
		 47,  85,  97,
		 44,  79, 109,
		126, 125,  92,
		 43,  74, 146,
		 20,  19, 127,
		128,  17,  77,
		 72, 146,  74,
		115,  99, 114,
		140, 122,  38,
		133, 105, 107,
		129, 100, 130,
		131, 144,  78,
		 95,  20, 127,
		123,  48, 112,
		102, 136, 101,
		 89, 111, 143,
		 28, 137,  84,
		133, 132,  50,
		125,  57, 100,
		 38, 123, 112,
		124,  57, 125,
		135, 134, 115,
		 23,  44,  46,
		136,  85,  52,
		 41,  62, 139,
		137,  11,  64,
		104,  48, 123,
		133, 138, 105,
		145, 139,  62,
		 25,   6,  26,
		  7,  30,  40,
		 46,  36, 140,
		141, 143,   0,
		132,  32,  63,
		 83, 104,  73,
		 19, 144, 127,
		142,  94, 141,
		 39,  13,  80,
		 92, 143, 126,
		127, 144, 131,
		 51,  61,   1,
		 91,   0,  59,
		 17,   7, 145,
		 43, 146, 147,
		146,  72, 147,
	};

	struct Shape
	{
		struct Type
		{
			enum Enum
			{
				Sphere,
				Aabb,
				Triangle,
				Capsule,
				Plane,
				Disk,
				Obb,
				Cone,
				Cylinder,

				Count
			};
		};

		Shape() : type(uint8_t(Type::Count)) {}
		Shape(const bx::Aabb& _a) : type(uint8_t(Type::Aabb)) { bx::memCopy(data, &_a, sizeof(_a)); }
		Shape(const bx::Capsule& _a) : type(uint8_t(Type::Capsule)) { bx::memCopy(data, &_a, sizeof(_a)); }
		Shape(const bx::Cone& _a) : type(uint8_t(Type::Cone)) { bx::memCopy(data, &_a, sizeof(_a)); }
		Shape(const bx::Cylinder& _a) : type(uint8_t(Type::Cylinder)) { bx::memCopy(data, &_a, sizeof(_a)); }
		Shape(const bx::Disk& _a) : type(uint8_t(Type::Disk)) { bx::memCopy(data, &_a, sizeof(_a)); }
		Shape(const bx::Obb& _a) : type(uint8_t(Type::Obb)) { bx::memCopy(data, &_a, sizeof(_a)); }
		Shape(const bx::Plane& _a) : type(uint8_t(Type::Plane)) { bx::memCopy(data, &_a, sizeof(_a)); }
		Shape(const bx::Sphere& _a) : type(uint8_t(Type::Sphere)) { bx::memCopy(data, &_a, sizeof(_a)); }
		Shape(const bx::Triangle& _a) : type(uint8_t(Type::Triangle)) { bx::memCopy(data, &_a, sizeof(_a)); }

		uint8_t data[64];
		uint8_t type;
	};

#define OVERLAP(_shapeType)                                                                                      \
	bool overlap(const _shapeType& _shapeA, const Shape& _shapeB)                                                \
	{                                                                                                            \
		switch (_shapeB.type)                                                                                    \
		{                                                                                                        \
		case Shape::Type::Aabb:     return bx::overlap(_shapeA, *reinterpret_cast<const bx::Aabb     *>(_shapeB.data) ); \
		case Shape::Type::Capsule:  return bx::overlap(_shapeA, *reinterpret_cast<const bx::Capsule  *>(_shapeB.data) ); \
		case Shape::Type::Cone:     return bx::overlap(_shapeA, *reinterpret_cast<const bx::Cone     *>(_shapeB.data) ); \
		case Shape::Type::Cylinder: return bx::overlap(_shapeA, *reinterpret_cast<const bx::Cylinder *>(_shapeB.data) ); \
		case Shape::Type::Disk:     return bx::overlap(_shapeA, *reinterpret_cast<const bx::Disk     *>(_shapeB.data) ); \
		case Shape::Type::Obb:      return bx::overlap(_shapeA, *reinterpret_cast<const bx::Obb      *>(_shapeB.data) ); \
		case Shape::Type::Plane:    return bx::overlap(_shapeA, *reinterpret_cast<const bx::Plane    *>(_shapeB.data) ); \
		case Shape::Type::Sphere:   return bx::overlap(_shapeA, *reinterpret_cast<const bx::Sphere   *>(_shapeB.data) ); \
		case Shape::Type::Triangle: return bx::overlap(_shapeA, *reinterpret_cast<const bx::Triangle *>(_shapeB.data) ); \
		}                                                                                                        \
		return false;                                                                                            \
	}

	OVERLAP(bx::Aabb);
	OVERLAP(bx::Capsule);
	OVERLAP(bx::Cone);
	OVERLAP(bx::Cylinder);
	OVERLAP(bx::Disk);
	OVERLAP(bx::Obb);
	OVERLAP(bx::Plane);
	OVERLAP(bx::Sphere);
	OVERLAP(bx::Triangle);

#undef OVERLAP

	void initA(Shape& _outShape, Shape::Type::Enum _type, bx::Vec3 _pos)
	{
		switch (_type)
		{
		case Shape::Type::Aabb:
		{
			bx::Aabb aabb;
			toAabb(aabb, _pos, { 0.5f, 0.5f, 0.5f });
			_outShape = Shape(aabb);
		}
		break;

		case Shape::Type::Capsule:
			_outShape = Shape(bx::Capsule
				{
					{ bx::add(_pos, {0.0f, -1.0f, 0.0f}) },
					{ bx::add(_pos, {0.0f,  1.0f, 0.0f}) },
					0.5f,
				});
			break;

		case Shape::Type::Cone:
			_outShape = Shape(bx::Cone
				{
					{ bx::add(_pos, {0.0f, -1.0f, 0.0f}) },
					{ bx::add(_pos, {0.0f,  1.0f, 0.0f}) },
					0.5f,
				});
			break;

		case Shape::Type::Cylinder:
			_outShape = Shape(bx::Cylinder
				{
					{ bx::add(_pos, {0.0f, -1.0f, 0.0f}) },
					{ bx::add(_pos, {0.0f,  1.0f, 0.0f}) },
					0.5f,
				});
			break;

		case Shape::Type::Disk:
			_outShape = Shape(bx::Disk
				{
					_pos,
					bx::normalize(bx::Vec3{0.0f, 1.0f, 1.0f}),
					0.5f,
				});
			break;

		case Shape::Type::Obb:
		{
			bx::Obb obb;
			bx::mtxSRT(obb.mtx
				, 0.25f
				, 1.0f
				, 0.25f
				, bx::toRad(50.0f)
				, bx::toRad(15.0f)
				, bx::toRad(45.0f)
				, _pos.x
				, _pos.y
				, _pos.z
			);
			_outShape = Shape(obb);
		}
		break;

		case Shape::Type::Sphere:
			_outShape = Shape(bx::Sphere{ _pos, 0.5f });
			break;

		case Shape::Type::Plane:
		{
			bx::Plane plane(bx::InitNone);
			bx::calcPlane(plane, bx::normalize(bx::Vec3{ 0.0f, 1.0f, 1.0f }), _pos);
			_outShape = Shape(plane);
		}
		break;

		case Shape::Type::Triangle:
			_outShape = Shape(bx::Triangle
				{
					{ bx::add(_pos, {-0.4f,  0.0f, -0.4f}) },
					{ bx::add(_pos, { 0.0f, -0.3f,  0.5f}) },
					{ bx::add(_pos, { 0.0f,  0.5f,  0.3f}) },
				});
			break;

		default: break;
		}
	}

	void initB(Shape& _outShape, Shape::Type::Enum _type, bx::Vec3 _pos)
	{
		switch (_type)
		{
		case Shape::Type::Aabb:
		{
			bx::Aabb aabb;
			toAabb(aabb, _pos, { 0.5f, 0.5f, 0.5f });
			_outShape = Shape(aabb);
		}
		break;

		case Shape::Type::Capsule:
			_outShape = Shape(bx::Capsule
				{
					{ bx::add(_pos, {0.0f, -1.0f, 0.1f}) },
					{ bx::add(_pos, {0.0f,  1.0f, 0.0f}) },
					0.2f,
				});
			break;

		case Shape::Type::Cone:
			_outShape = Shape(bx::Cone
				{
					{ bx::add(_pos, {0.0f, -1.0f, 0.1f}) },
					{ bx::add(_pos, {0.0f,  1.0f, 0.0f}) },
					0.2f,
				});
			break;

		case Shape::Type::Cylinder:
			_outShape = Shape(bx::Cylinder
				{
					{ bx::add(_pos, {0.0f, -1.0f, 0.1f}) },
					{ bx::add(_pos, {0.0f,  1.0f, 0.0f}) },
					0.2f,
				});
			break;

		case Shape::Type::Disk:
			_outShape = Shape(bx::Disk
				{
					_pos,
					bx::normalize(bx::Vec3{1.0f, 1.0f, 0.0f}),
					0.5f,
				});
			break;

		case Shape::Type::Obb:
		{
			bx::Obb obb;
			bx::mtxSRT(obb.mtx
				, 1.0f
				, 0.25f
				, 0.25f
				, bx::toRad(10.0f)
				, bx::toRad(30.0f)
				, bx::toRad(70.0f)
				, _pos.x
				, _pos.y
				, _pos.z
			);
			_outShape = Shape(obb);
		}
		break;

		case Shape::Type::Plane:
		{
			bx::Plane plane(bx::InitNone);
			bx::calcPlane(plane, bx::normalize(bx::Vec3{ 1.0f, 1.0f, 0.0f }), _pos);
			_outShape = Shape(plane);
		}
		break;

		case Shape::Type::Sphere:
			_outShape = Shape(bx::Sphere{ _pos, 0.5f });
			break;

		case Shape::Type::Triangle:
			_outShape = Shape(bx::Triangle
				{
					{ bx::add(_pos, {-0.4f,  0.0f, -0.4f}) },
					{ bx::add(_pos, {-0.5f, -0.3f,  0.0f}) },
					{ bx::add(_pos, { 0.3f,  0.5f,  0.0f}) },
				});
			break;

		default: break;
		}
	}

	int32_t overlap(const Shape& _shapeA, const Shape& _shapeB)
	{
		switch (_shapeA.type)
		{
		case Shape::Type::Aabb:     return ::overlap(*reinterpret_cast<const bx::Aabb*>(_shapeA.data), _shapeB);
		case Shape::Type::Capsule:  return ::overlap(*reinterpret_cast<const bx::Capsule*>(_shapeA.data), _shapeB);
		case Shape::Type::Cone:     return ::overlap(*reinterpret_cast<const bx::Cone*>(_shapeA.data), _shapeB);
		case Shape::Type::Cylinder: return ::overlap(*reinterpret_cast<const bx::Cylinder*>(_shapeA.data), _shapeB);
		case Shape::Type::Disk:     return ::overlap(*reinterpret_cast<const bx::Disk*>(_shapeA.data), _shapeB);
		case Shape::Type::Obb:      return ::overlap(*reinterpret_cast<const bx::Obb*>(_shapeA.data), _shapeB);
		case Shape::Type::Plane:    return ::overlap(*reinterpret_cast<const bx::Plane*>(_shapeA.data), _shapeB);
		case Shape::Type::Sphere:   return ::overlap(*reinterpret_cast<const bx::Sphere*>(_shapeA.data), _shapeB);
		case Shape::Type::Triangle: return ::overlap(*reinterpret_cast<const bx::Triangle*>(_shapeA.data), _shapeB);
		}

		return 2;
	}

	void draw(DebugDrawEncoder& _dde, const Shape& _shape, const bx::Vec3 _pos)
	{
		switch (_shape.type)
		{
		case Shape::Type::Aabb:     _dde.draw(*reinterpret_cast<const bx::Aabb*>(_shape.data)); break;
		case Shape::Type::Capsule:  _dde.draw(*reinterpret_cast<const bx::Capsule*>(_shape.data)); break;
		case Shape::Type::Cone:     _dde.draw(*reinterpret_cast<const bx::Cone*>(_shape.data)); break;
		case Shape::Type::Cylinder: _dde.draw(*reinterpret_cast<const bx::Cylinder*>(_shape.data)); break;
		case Shape::Type::Disk:     _dde.draw(*reinterpret_cast<const bx::Disk*>(_shape.data)); break;
		case Shape::Type::Obb:      _dde.draw(*reinterpret_cast<const bx::Obb*>(_shape.data)); break;
		case Shape::Type::Plane: { _dde.drawGrid(reinterpret_cast<const bx::Plane*>(_shape.data)->normal, _pos, 9, 0.3f); } break;
		case Shape::Type::Sphere:   _dde.draw(*reinterpret_cast<const bx::Sphere*>(_shape.data)); break;
		case Shape::Type::Triangle: _dde.draw(*reinterpret_cast<const bx::Triangle*>(_shape.data)); break;
		}
	}

	void imageCheckerboard(void* _dst, uint32_t _width, uint32_t _height, uint32_t _step, uint32_t _0, uint32_t _1)
	{
		uint32_t* dst = (uint32_t*)_dst;
		for (uint32_t yy = 0; yy < _height; ++yy)
		{
			for (uint32_t xx = 0; xx < _width; ++xx)
			{
				uint32_t abgr = ((xx / _step) & 1) ^ ((yy / _step) & 1) ? _1 : _0;
				*dst++ = abgr;
			}
		}
	}

#pragma endregion
namespace WireFrame
{
	struct Camera
	{
		Camera()
		{
			reset();
		}

		void reset()
		{
			m_target.curr = bx::InitZero;
			m_target.dest = bx::InitZero;

			m_pos.curr = { 0.0f, 0.0f, -2.0f };
			m_pos.dest = { 0.0f, 0.0f, -2.0f };

			m_orbit[0] = 0.0f;
			m_orbit[1] = 0.0f;
		}

		void mtxLookAt(float* _outViewMtx)
		{
			bx::mtxLookAt(_outViewMtx, m_pos.curr, m_target.curr);
		}

		void orbit(float _dx, float _dy)
		{
			m_orbit[0] += _dx;
			m_orbit[1] += _dy;
		}

		void dolly(float _dz)
		{
			const float cnear = 1.0f;
			const float cfar = 100.0f;

			const bx::Vec3 toTarget = bx::sub(m_target.dest, m_pos.dest);
			const float toTargetLen = bx::length(toTarget);
			const float invToTargetLen = 1.0f / (toTargetLen + bx::kFloatSmallest);
			const bx::Vec3 toTargetNorm = bx::mul(toTarget, invToTargetLen);

			float delta = toTargetLen * _dz;
			float newLen = toTargetLen + delta;
			if ((cnear < newLen || _dz < 0.0f)
				&& (newLen < cfar || _dz > 0.0f))
			{
				m_pos.dest = bx::mad(toTargetNorm, delta, m_pos.dest);
			}
		}

		void consumeOrbit(float _amount)
		{
			float consume[2];
			consume[0] = m_orbit[0] * _amount;
			consume[1] = m_orbit[1] * _amount;
			m_orbit[0] -= consume[0];
			m_orbit[1] -= consume[1];

			const bx::Vec3 toPos = bx::sub(m_pos.curr, m_target.curr);
			const float toPosLen = bx::length(toPos);
			const float invToPosLen = 1.0f / (toPosLen + bx::kFloatSmallest);
			const bx::Vec3 toPosNorm = bx::mul(toPos, invToPosLen);

			float ll[2];
			bx::toLatLong(&ll[0], &ll[1], toPosNorm);
			ll[0] += consume[0];
			ll[1] -= consume[1];
			ll[1] = bx::clamp(ll[1], 0.02f, 0.98f);

			const bx::Vec3 tmp = bx::fromLatLong(ll[0], ll[1]);
			const bx::Vec3 diff = bx::mul(bx::sub(tmp, toPosNorm), toPosLen);

			m_pos.curr = bx::add(m_pos.curr, diff);
			m_pos.dest = bx::add(m_pos.dest, diff);
		}

		void update(float _dt)
		{
			const float amount = bx::min(_dt / 0.12f, 1.0f);

			consumeOrbit(amount);

			m_target.curr = bx::lerp(m_target.curr, m_target.dest, amount);
			m_pos.curr = bx::lerp(m_pos.curr, m_pos.dest, amount);
		}

		void envViewMtx(float* _mtx)
		{
			const bx::Vec3 toTarget = bx::sub(m_target.curr, m_pos.curr);
			const float toTargetLen = bx::length(toTarget);
			const float invToTargetLen = 1.0f / (toTargetLen + bx::kFloatSmallest);
			const bx::Vec3 toTargetNorm = bx::mul(toTarget, invToTargetLen);

			const bx::Vec3 right = bx::normalize(bx::cross({ 0.0f, 1.0f, 0.0f }, toTargetNorm));
			const bx::Vec3 up = bx::normalize(bx::cross(toTargetNorm, right));

			_mtx[0] = right.x;
			_mtx[1] = right.y;
			_mtx[2] = right.z;
			_mtx[3] = 0.0f;
			_mtx[4] = up.x;
			_mtx[5] = up.y;
			_mtx[6] = up.z;
			_mtx[7] = 0.0f;
			_mtx[8] = toTargetNorm.x;
			_mtx[9] = toTargetNorm.y;
			_mtx[10] = toTargetNorm.z;
			_mtx[11] = 0.0f;
			_mtx[12] = 0.0f;
			_mtx[13] = 0.0f;
			_mtx[14] = 0.0f;
			_mtx[15] = 1.0f;
		}

		struct Interp3f
		{
			bx::Vec3 curr = bx::InitNone;
			bx::Vec3 dest = bx::InitNone;
		};

		Interp3f m_target;
		Interp3f m_pos;
		float m_orbit[2];
	};

	struct Mouse
	{
		Mouse()
		{
			m_dx = 0.0f;
			m_dy = 0.0f;
			m_prevMx = 0.0f;
			m_prevMx = 0.0f;
			m_scroll = 0;
			m_scrollPrev = 0;
		}

		void update(float _mx, float _my, int32_t _mz, uint32_t _width, uint32_t _height)
		{
			const float widthf = float(int32_t(_width));
			const float heightf = float(int32_t(_height));

			// Delta movement.
			m_dx = float(_mx - m_prevMx) / widthf;
			m_dy = float(_my - m_prevMy) / heightf;

			m_prevMx = _mx;
			m_prevMy = _my;

			// Scroll.
			m_scroll = _mz - m_scrollPrev;
			m_scrollPrev = _mz;
		}

		float m_dx; // Screen space.
		float m_dy;
		float m_prevMx;
		float m_prevMy;
		int32_t m_scroll;
		int32_t m_scrollPrev;
	};

	struct MeshMtx
	{
		MeshMtx()
		{
			m_mesh = NULL;
		}

		void init(const char* _path
			, float _scale = 1.0f
			, float _rotX = 0.0f
			, float _rotY = 0.0f
			, float _rotZ = 0.0f
			, float _transX = 0.0f
			, float _transY = 0.0f
			, float _transZ = 0.0f
		)
		{
			m_mesh = meshLoad(_path);
			bx::mtxSRT(m_mtx
				, _scale
				, _scale
				, _scale
				, _rotX
				, _rotY
				, _rotZ
				, _transX
				, _transY
				, _transZ
			);
		}

		void destroy()
		{
			if (NULL != m_mesh)
			{
				meshUnload(m_mesh);
			}
		}

		Mesh* m_mesh;
		float m_mtx[16];
	};

	struct Uniforms
	{
		enum { NumVec4 = 3 };

		void init()
		{
			m_camPos[0] = 0.0f;
			m_camPos[1] = 1.0f;
			m_camPos[2] = -2.5f;
			m_wfColor[0] = 1.0f;
			m_wfColor[1] = 0.0f;
			m_wfColor[2] = 0.0f;
			m_wfColor[3] = 1.0f;
			m_drawEdges = 0.0f;
			m_wfThickness = 1.5f;

			u_params = bgfx::createUniform("u_params", bgfx::UniformType::Vec4, NumVec4);
		}

		void submit()
		{
			bgfx::setUniform(u_params, m_params, NumVec4);
		}

		void destroy()
		{
			bgfx::destroy(u_params);
		}

		union
		{
			struct
			{
				/*0*/struct { float m_camPos[3], m_unused0; };
				/*1*/struct { float m_wfColor[4]; };
				/*2*/struct { float m_drawEdges, m_wfThickness, m_unused2[2]; };
			};

			float m_params[NumVec4 * 4];
		};

		bgfx::UniformHandle u_params;
	};
}
struct PosColorVertex
{
	float m_x;
	float m_y;
	float m_z;
	uint32_t m_abgr;

	static void init()
	{
		ms_layout
			.begin()
			.add(bgfx::Attrib::Position, 3, bgfx::AttribType::Float)
			.add(bgfx::Attrib::Color0,   4, bgfx::AttribType::Uint8, true)
			.end();
	};

	static bgfx::VertexLayout ms_layout;
};

bgfx::VertexLayout PosColorVertex::ms_layout;

static PosColorVertex s_cubeVertices[8] =
{
	{-1.0f,  1.0f,  1.0f, 0xff000000 },
	{ 1.0f,  1.0f,  1.0f, 0xff0000ff },
	{-1.0f, -1.0f,  1.0f, 0xff00ff00 },
	{ 1.0f, -1.0f,  1.0f, 0xff00ffff },
	{-1.0f,  1.0f, -1.0f, 0xffff0000 },
	{ 1.0f,  1.0f, -1.0f, 0xffff00ff },
	{-1.0f, -1.0f, -1.0f, 0xffffff00 },
	{ 1.0f, -1.0f, -1.0f, 0xffffffff },
};

static const uint16_t s_cubeIndices[36] =
{
	0, 1, 2, // 0
	1, 3, 2,
	4, 6, 5, // 2
	5, 6, 7,
	0, 2, 4, // 4
	4, 2, 6,
	1, 5, 3, // 6
	5, 7, 3,
	0, 4, 1, // 8
	4, 5, 1,
	2, 3, 6, // 10
	6, 3, 7,
};
#pragma 01cube
#pragma region  01cube
static const uint16_t s_cubeTriStrip[] =
{
	0, 1, 2,
	3,
	7,
	1,
	5,
	0,
	4,
	2,
	6,
	7,
	4,
	5,
};

static const uint16_t s_cubeLineList[] =
{
	0, 1,
	0, 2,
	0, 4,
	1, 3,
	1, 5,
	2, 3,
	2, 6,
	3, 7,
	4, 5,
	4, 6,
	5, 7,
	6, 7,
};

static const uint16_t s_cubeLineStrip[] =
{
	0, 2, 3, 1, 5, 7, 6, 4,
	0, 2, 6, 4, 5, 7, 3, 1,
	0,
};

static const uint16_t s_cubePoints[] =
{
	0, 1, 2, 3, 4, 5, 6, 7
};

static const char* s_ptNames[]
{
	"Triangle List",
	"Triangle Strip",
	"Lines",
	"Line Strip",
	"Points",
};

static const uint64_t s_ptState[]
{
	UINT64_C(0),
	BGFX_STATE_PT_TRISTRIP,
	BGFX_STATE_PT_LINES,
	BGFX_STATE_PT_LINESTRIP,
	BGFX_STATE_PT_POINTS,
};
BX_STATIC_ASSERT(BX_COUNTOF(s_ptState) == BX_COUNTOF(s_ptNames));
#pragma endregion

#pragma region oit
struct PosColorTexCoord0Vertex
{
	float m_x;
	float m_y;
	float m_z;
	uint32_t m_rgba;
	float m_u;
	float m_v;

	static void init()
	{
		ms_layout
			.begin()
			.add(bgfx::Attrib::Position, 3, bgfx::AttribType::Float)
			.add(bgfx::Attrib::Color0, 4, bgfx::AttribType::Uint8, true)
			.add(bgfx::Attrib::TexCoord0, 2, bgfx::AttribType::Float)
			.end();
	}

	static bgfx::VertexLayout ms_layout;
};

bgfx::VertexLayout PosColorTexCoord0Vertex::ms_layout;
static float s_texelHalf = 0.0f;
static bool s_flipV = false;
inline void mtxProj(float* _result, float _fovy, float _aspect, float _near, float _far)
{
	bx::mtxProj(_result, _fovy, _aspect, _near, _far, s_flipV);
}

void screenSpaceQuad(float _textureWidth, float _textureHeight, bool _originBottomLeft = false, float _width = 1.0f, float _height = 1.0f)
{
	if (3 == bgfx::getAvailTransientVertexBuffer(3, PosColorTexCoord0Vertex::ms_layout))
	{
		bgfx::TransientVertexBuffer vb;
		bgfx::allocTransientVertexBuffer(&vb, 3, PosColorTexCoord0Vertex::ms_layout);
		PosColorTexCoord0Vertex* vertex = (PosColorTexCoord0Vertex*)vb.data;

		const float zz = 0.0f;

		const float minx = -_width;
		const float maxx = _width;
		const float miny = 0.0f;
		const float maxy = _height * 2.0f;

		const float texelHalfW = s_texelHalf / _textureWidth;
		const float texelHalfH = s_texelHalf / _textureHeight;
		const float minu = -1.0f + texelHalfW;
		const float maxu = 1.0f + texelHalfW;

		float minv = texelHalfH;
		float maxv = 2.0f + texelHalfH;

		if (_originBottomLeft)
		{
			float tmp = minv;
			minv = maxv;
			maxv = tmp;

			minv -= 1.0f;
			maxv -= 1.0f;
		}

		vertex[0].m_x = minx;
		vertex[0].m_y = miny;
		vertex[0].m_z = zz;
		vertex[0].m_rgba = 0xffffffff;
		vertex[0].m_u = minu;
		vertex[0].m_v = minv;

		vertex[1].m_x = maxx;
		vertex[1].m_y = miny;
		vertex[1].m_z = zz;
		vertex[1].m_rgba = 0xffffffff;
		vertex[1].m_u = maxu;
		vertex[1].m_v = minv;

		vertex[2].m_x = maxx;
		vertex[2].m_y = maxy;
		vertex[2].m_z = zz;
		vertex[2].m_rgba = 0xffffffff;
		vertex[2].m_u = maxu;
		vertex[2].m_v = maxv;

		bgfx::setVertexBuffer(0, &vb);
	}
}

#pragma endregion


class ExampleCubes : public entry::AppI
{
public:
	ExampleCubes(const char* _name, const char* _description, const char* _url)
		: entry::AppI(_name, _description, _url){
		if (m_current_example_type == ExampleType::_01_Cubes){
			m_pt = 0;
			m_r = m_g = m_b = m_a = true;
		}
	}

	void init(int32_t _argc, const char* const* _argv, uint32_t _width, uint32_t _height) override
	{
		Args args(_argc, _argv);

		m_width = _width;
		m_height = _height;
		m_debug = BGFX_DEBUG_NONE;
		if (m_current_example_type == ExampleType::_05_Instancing) {
			m_debug = BGFX_DEBUG_TEXT;
		}
		m_reset = BGFX_RESET_VSYNC;
		if (m_current_example_type == ExampleType::_05_Instancing) {
			m_useInstancing = true;
			m_lastFrameMissing = 0;
			m_sideSize = 11;
		}
		bgfx::Init init;
		init.type = args.m_type;
		init.vendorId = args.m_pciId;
		init.platformData.nwh = entry::getNativeWindowHandle(entry::kDefaultWindowHandle);
		init.platformData.ndt = entry::getNativeDisplayHandle();
		init.platformData.type = entry::getNativeWindowHandleType();
		init.resolution.width = m_width;
		init.resolution.height = m_height;
		init.resolution.reset = m_reset;
		bgfx::init(init);

		// Enable debug text.
		bgfx::setDebug(m_debug);
		if (!(m_current_example_type == ExampleType::_19_Oit)){
				// Set view 0 clear state.
				bgfx::setViewClear(0
					, BGFX_CLEAR_COLOR | BGFX_CLEAR_DEPTH
					, 0x303030ff
					, 1.0f
					, 0
				);
		}
		imguiCreate();//m_fontManager shouf init after imguiCreate
		if (m_current_example_type == ExampleType::_01_Cubes){
			// Create vertex stream declaration.
			PosColorVertex::init();

			// Create static vertex buffer.
			m_vbh = bgfx::createVertexBuffer(
				// Static data can be passed with bgfx::makeRef
				bgfx::makeRef(s_cubeVertices, sizeof(s_cubeVertices))
				, PosColorVertex::ms_layout
			);

			// Create static index buffer for triangle list rendering.
			m_cube_ibh[0] = bgfx::createIndexBuffer(
				// Static data can be passed with bgfx::makeRef
				bgfx::makeRef(s_cubeIndices, sizeof(s_cubeIndices))
			);

			// Create static index buffer for triangle strip rendering.
			m_cube_ibh[1] = bgfx::createIndexBuffer(
				// Static data can be passed with bgfx::makeRef
				bgfx::makeRef(s_cubeTriStrip, sizeof(s_cubeTriStrip))
			);

			// Create static index buffer for line list rendering.
			m_cube_ibh[2] = bgfx::createIndexBuffer(
				// Static data can be passed with bgfx::makeRef
				bgfx::makeRef(s_cubeLineList, sizeof(s_cubeLineList))
			);

			// Create static index buffer for line strip rendering.
			m_cube_ibh[3] = bgfx::createIndexBuffer(
				// Static data can be passed with bgfx::makeRef
				bgfx::makeRef(s_cubeLineStrip, sizeof(s_cubeLineStrip))
			);

			// Create static index buffer for point list rendering.
			m_cube_ibh[4] = bgfx::createIndexBuffer(
				// Static data can be passed with bgfx::makeRef
				bgfx::makeRef(s_cubePoints, sizeof(s_cubePoints))
			);

			// Create program from shaders.
			m_program = loadProgram("vs_cubes", "fs_cubes");
		}
		else if (m_current_example_type == ExampleType::_04_Mesh)
		{
			u_time = bgfx::createUniform("u_time", bgfx::UniformType::Vec4);
			// Create program from shaders.
			m_program = loadProgram("vs_mesh", "fs_mesh");
			m_mesh = meshLoad("meshes/bunny.bin");
		}
		else if (m_current_example_type == ExampleType::_05_Instancing) {
			// Create vertex stream declaration.
			PosColorVertex::init();
			// Create static vertex buffer.
			m_vbh = bgfx::createVertexBuffer(
				bgfx::makeRef(s_cubeVertices, sizeof(s_cubeVertices))
				, PosColorVertex::ms_layout
			);

			// Create static index buffer.
			m_ibh = bgfx::createIndexBuffer(
				bgfx::makeRef(s_cubeIndices, sizeof(s_cubeIndices))
			);

			// Create program from shaders.
			m_program = loadProgram("vs_instancing", "fs_instancing");
			m_program_non_instanced = loadProgram("vs_cubes", "fs_cubes");
		}
		else if (m_current_example_type == ExampleType::_10_Font) {
			// Init the text rendering system.
			m_fontManager = new FontManager(512);
			m_textBufferManager = new TextBufferManager(m_fontManager);

			// Load some TTF files.
			for (uint32_t ii = 0; ii < numFonts; ++ii)
			{
				// Instantiate a usable font.
				m_fontFiles[ii] = loadTtf(m_fontManager, s_fontFilePath[ii]);
				m_fonts[ii] = m_fontManager->createFontByPixelSize(m_fontFiles[ii], 0, 32);

				// Preload glyphs and blit them to atlas.
				m_fontManager->preloadGlyph(m_fonts[ii], L"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ. \n");

				// You can unload the truetype files at this stage, but in that
				// case, the set of glyph's will be limited to the set of preloaded
				// glyph.
				m_fontManager->destroyTtf(m_fontFiles[ii]);
			}

			m_fontAwesomeTtf = loadTtf(m_fontManager, "font/fontawesome-webfont.ttf");
			m_fontKenneyTtf = loadTtf(m_fontManager, "font/kenney-icon-font.ttf");

			// This font doesn't have any preloaded glyph's but the truetype file
			// is loaded so glyph will be generated as needed.
			m_fontAwesome72 = m_fontManager->createFontByPixelSize(m_fontAwesomeTtf, 0, 72);
			m_fontKenney64 = m_fontManager->createFontByPixelSize(m_fontKenneyTtf, 0, 64);

			m_visitorTtf = loadTtf(m_fontManager, "font/visitor1.ttf");

			// This font doesn't have any preloaded glyph's but the truetype file
			// is loaded so glyph will be generated as needed.
			m_visitor10 = m_fontManager->createFontByPixelSize(m_visitorTtf, 0, 10);

			//create a static text buffer compatible with alpha font
			//a static text buffer content cannot be modified after its first submit.
			m_staticText = m_textBufferManager->createTextBuffer(FONT_TYPE_ALPHA, BufferType::Static);

			// The pen position represent the top left of the box of the first line
			// of text.
			m_textBufferManager->setPenPosition(m_staticText, 24.0f, 100.0f);

			for (uint32_t ii = 0; ii < numFonts; ++ii){
				// Add some text to the buffer.
				// The position of the pen is adjusted when there is an endline.
				m_textBufferManager->appendText(m_staticText, m_fonts[ii], L"The quick brown fox jumps over the lazy dog\n");
			}

			// Now write some styled text.

			// Setup style colors.
			m_textBufferManager->setBackgroundColor(m_staticText, 0x551111ff);
			m_textBufferManager->setUnderlineColor(m_staticText, 0xff2222ff);
			m_textBufferManager->setOverlineColor(m_staticText, 0x2222ffff);
			m_textBufferManager->setStrikeThroughColor(m_staticText, 0x22ff22ff);

			// Background.
			m_textBufferManager->setStyle(m_staticText, STYLE_BACKGROUND);
			m_textBufferManager->appendText(m_staticText, m_fonts[0], L"The quick ");

			// Strike-through.
			m_textBufferManager->setStyle(m_staticText, STYLE_STRIKE_THROUGH);
			m_textBufferManager->appendText(m_staticText, m_fonts[0], L"brown fox ");

			// Overline.
			m_textBufferManager->setStyle(m_staticText, STYLE_OVERLINE);
			m_textBufferManager->appendText(m_staticText, m_fonts[0], L"jumps over ");

			// Underline.
			m_textBufferManager->setStyle(m_staticText, STYLE_UNDERLINE);
			m_textBufferManager->appendText(m_staticText, m_fonts[0], L"the lazy ");

			// Background + strike-through.
			m_textBufferManager->setStyle(m_staticText, STYLE_BACKGROUND | STYLE_STRIKE_THROUGH);
			m_textBufferManager->appendText(m_staticText, m_fonts[0], L"dog\n");

			m_textBufferManager->setStyle(m_staticText, STYLE_NORMAL);
			m_textBufferManager->appendText(m_staticText, m_fontAwesome72,
				" " ICON_FA_POWER_OFF
				" " ICON_FA_TWITTER_SQUARE
				" " ICON_FA_CERTIFICATE
				" " ICON_FA_FLOPPY_O
				" " ICON_FA_GITHUB
				" " ICON_FA_GITHUB_ALT
				"\n"
			);
			m_textBufferManager->appendText(m_staticText, m_fontKenney64,
				" " ICON_KI_COMPUTER
				" " ICON_KI_JOYSTICK
				" " ICON_KI_EXLAMATION
				" " ICON_KI_STAR
				" " ICON_KI_BUTTON_START
				" " ICON_KI_DOWNLOAD
				"\n"
			);
			// Create a transient buffer for real-time data.
			m_transientText = m_textBufferManager->createTextBuffer(FONT_TYPE_ALPHA, BufferType::Transient);
		}
		else if (m_current_example_type == ExampleType::_11_Font_sdf){
			uint32_t size;
			m_txtFile = load("text/sherlock_holmes_a_scandal_in_bohemia_arthur_conan_doyle.txt", &size);
			m_bigText = bx::StringView((const char*)m_txtFile, size);

			// Set up some defaults.
			m_outlineColor = ImVec4(1.0f, 0.0f, 0.0f, 1.0f);
			m_outlineWidth = 1.0f;
			m_dropShadowColor = ImVec4(0.0f, 0.0f, 0.0f, 0.35f);
			m_dropShadowOffsetX = 1.0f;
			m_dropShadowOffsetY = 1.0f;
			m_dropShadowSoftener = 2.0f;

			m_textScroll = 0.0f;
			m_textRotation = 0.0f;
			m_textScale = 1.0f;
			m_textSize = 14.0f;

			// Init the text rendering system.
			m_fontManager = NULL;
			m_textBufferManager = NULL;
			m_font = BGFX_INVALID_HANDLE;
			m_fontSdf = BGFX_INVALID_HANDLE;
			m_fontScaled = BGFX_INVALID_HANDLE;
			m_scrollableBuffer = BGFX_INVALID_HANDLE;

			initializeFont(FONT_TYPE_DISTANCE);

			m_lineCount = m_metrics.getLineCount(m_bigText);

			m_visibleLineCount = 20.0f;

			m_textBegin = 0;
			m_textEnd = 0;
			m_metrics.getSubText(m_bigText, 0, (uint32_t)m_visibleLineCount, m_textBegin, m_textEnd);

			initializeTextBuffer(FONT_TYPE_DISTANCE);

			applyTextBufferAttributes();

			m_textBufferManager->appendText(m_scrollableBuffer, m_fontScaled, m_textBegin, m_textEnd);
		}
		else if (m_current_example_type == ExampleType::_30_Picking)
		{
			// ID buffer clears to black, which represents clicking on nothing (background)
			bgfx::setViewClear(RENDER_PASS_ID
				, BGFX_CLEAR_COLOR | BGFX_CLEAR_DEPTH
				, 0x000000ff
				, 1.0f
				, 0
			);

			// Create uniforms
			u_tint = bgfx::createUniform("u_tint", bgfx::UniformType::Vec4); // Tint for when you click on items
			u_id = bgfx::createUniform("u_id", bgfx::UniformType::Vec4); // ID for drawing into ID buffer

			// Create program from shaders.
			m_shadingProgram = loadProgram("vs_picking_shaded", "fs_picking_shaded"); // Blinn shading
			m_idProgram = loadProgram("vs_picking_shaded", "fs_picking_id");     // Shader for drawing into ID buffer

			static const char* meshPaths[] =
			{
				"meshes/orb.bin",
				"meshes/column.bin",
				"meshes/bunny.bin",
				"meshes/cube.bin",
				"meshes/tree.bin",
				"meshes/hollowcube.bin",
			};

			static const float meshScale[] =
			{
				0.5f,
				0.05f,
				0.5f,
				0.25f,
				0.05f,
				0.05f,
			};

			m_highlighted = UINT32_MAX;
			m_reading = 0;
			m_currFrame = UINT32_MAX;
			m_fov = 3.0f;
			m_cameraSpin = false;

			bx::RngMwc mwc;  // Random number generator
			for (uint32_t ii = 0; ii < 12; ++ii)
			{
				m_meshes[ii] = meshLoad(meshPaths[ii % BX_COUNTOF(meshPaths)]);
				m_meshScale[ii] = meshScale[ii % BX_COUNTOF(meshPaths)];
				// For the sake of this example, we'll give each mesh a random color,  so the debug output looks colorful.
				// In an actual app, you'd probably just want to count starting from 1
				uint32_t rr = mwc.gen() % 256;
				uint32_t gg = mwc.gen() % 256;
				uint32_t bb = mwc.gen() % 256;
				m_idsF[ii][0] = rr / 255.0f;
				m_idsF[ii][1] = gg / 255.0f;
				m_idsF[ii][2] = bb / 255.0f;
				m_idsF[ii][3] = 1.0f;
				m_idsU[ii] = rr + (gg << 8) + (bb << 16) + (255u << 24);
			}

			m_timeOffset = bx::getHPCounter();

			// Set up ID buffer, which has a color target and depth buffer
			m_pickingRT = bgfx::createTexture2D(ID_DIM, ID_DIM, false, 1, bgfx::TextureFormat::RGBA8, 0
				| BGFX_TEXTURE_RT
				| BGFX_SAMPLER_MIN_POINT
				| BGFX_SAMPLER_MAG_POINT
				| BGFX_SAMPLER_MIP_POINT
				| BGFX_SAMPLER_U_CLAMP
				| BGFX_SAMPLER_V_CLAMP
			);
			m_pickingRTDepth = bgfx::createTexture2D(ID_DIM, ID_DIM, false, 1, bgfx::TextureFormat::D32F, 0
				| BGFX_TEXTURE_RT
				| BGFX_SAMPLER_MIN_POINT
				| BGFX_SAMPLER_MAG_POINT
				| BGFX_SAMPLER_MIP_POINT
				| BGFX_SAMPLER_U_CLAMP
				| BGFX_SAMPLER_V_CLAMP
			);

			// CPU texture for blitting to and reading ID buffer so we can see what was clicked on.
			// Impossible to read directly from a render target, you *must* blit to a CPU texture
			// first. Algorithm Overview: Render on GPU -> Blit to CPU texture -> Read from CPU
			// texture.
			m_blitTex = bgfx::createTexture2D(ID_DIM, ID_DIM, false, 1, bgfx::TextureFormat::RGBA8, 0
				| BGFX_TEXTURE_BLIT_DST
				| BGFX_TEXTURE_READ_BACK
				| BGFX_SAMPLER_MIN_POINT
				| BGFX_SAMPLER_MAG_POINT
				| BGFX_SAMPLER_MIP_POINT
				| BGFX_SAMPLER_U_CLAMP
				| BGFX_SAMPLER_V_CLAMP
			);

			bgfx::TextureHandle rt[2] =
			{
				m_pickingRT,
				m_pickingRTDepth
			};
			m_pickingFB = bgfx::createFrameBuffer(BX_COUNTOF(rt), rt, true);

		}
		else if (m_current_example_type == ExampleType::_29_Debugdraw) {
			cameraCreate();

			cameraSetPosition({ 0.0f, 2.0f, -12.0f });
			cameraSetVerticalAngle(0.0f);

			ddInit();

			uint8_t data[32 * 32 * 4];
			imageCheckerboard(data, 32, 32, 4, 0xff808080, 0xffc0c0c0);

			m_sprite = ddCreateSprite(32, 32, data);
			m_bunny = ddCreateGeometry(
				BX_COUNTOF(s_bunnyVertices)
				, s_bunnyVertices
				, BX_COUNTOF(s_bunnyTriList)
				, s_bunnyTriList
			);
        }
		else if (m_current_example_type == ExampleType::_28_Wireframe){
			m_wfProgram = loadProgram("vs_wf_wireframe", "fs_wf_wireframe");
			m_meshProgram = loadProgram("vs_wf_mesh", "fs_wf_mesh");

			m_uniforms.init();

			m_wf_meshes[0].init("meshes/bunny.bin", 1.0f, 0.0f, bx::kPi, 0.0f, 0.0f, -0.8f, 0.0f);
			m_wf_meshes[1].init("meshes/hollowcube.bin", 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f);
			m_wf_meshes[2].init("meshes/orb.bin", 1.2f, 0.0f, 0.0f, 0.0f, 0.0f, -0.65f, 0.0f);

			m_oldWidth = 0;
			m_oldHeight = 0;
			m_oldReset = m_reset;

			m_meshSelection = 1;
			m_drawMode = DrawMode::WireframeShaded;
		}
		else if (m_current_example_type == ExampleType::_19_Oit) {
			// Create vertex stream declaration.
			PosColorVertex::init();
			PosColorTexCoord0Vertex::init();
			// Get renderer capabilities info.
			const bgfx::Caps* caps = bgfx::getCaps();
			// Setup root path for binary shaders. Shader binaries are different
			// for each renderer.
			switch (caps->rendererType){
			default:
				break;
			case bgfx::RendererType::OpenGL:
			case bgfx::RendererType::OpenGLES:
				s_flipV = true;
				break;
			}
			// Create static vertex buffer.
			m_vbh = bgfx::createVertexBuffer(
				bgfx::makeRef(s_cubeVertices, sizeof(s_cubeVertices))
				, PosColorVertex::ms_layout
			);

			// Create static index buffer.
			m_ibh = bgfx::createIndexBuffer(bgfx::makeRef(s_cubeIndices, sizeof(s_cubeIndices)));

			// Create texture sampler uniforms.
			s_texColor0 = bgfx::createUniform("s_texColor0", bgfx::UniformType::Sampler);
			s_texColor1 = bgfx::createUniform("s_texColor1", bgfx::UniformType::Sampler);
			u_color = bgfx::createUniform("u_color", bgfx::UniformType::Vec4);

			m_blend = loadProgram("vs_oit", "fs_oit");
			m_wbSeparatePass = loadProgram("vs_oit", "fs_oit_wb_separate");
			m_wbSeparateBlit = loadProgram("vs_oit_blit", "fs_oit_wb_separate_blit");
			m_wbPass = loadProgram("vs_oit", "fs_oit_wb");
			m_wbBlit = loadProgram("vs_oit_blit", "fs_oit_wb_blit");

			m_fbtextures[0].idx = bgfx::kInvalidHandle;
			m_fbtextures[1].idx = bgfx::kInvalidHandle;
			m_fbh.idx = bgfx::kInvalidHandle;

			m_mode = 1;
			m_frontToBack = true;
			m_fadeInOut = false;

			m_oldWidth = 0;
			m_oldHeight = 0;
			m_oldReset = m_reset;

			m_mrtSupported = true
				&& 2 <= caps->limits.maxFBAttachments
				&& bgfx::isTextureValid(0, false, 1, bgfx::TextureFormat::RGBA16F, BGFX_TEXTURE_RT)
				&& bgfx::isTextureValid(0, false, 1, bgfx::TextureFormat::R16F, BGFX_TEXTURE_RT)
				;
		}
		m_timeOffset = bx::getHPCounter();//very important//Get the current value of the high-precision timer//getHPFrequency
	}

	virtual int shutdown() override
	{
		imguiDestroy();
		// Cleanup.
		if (m_current_example_type == ExampleType::_01_Cubes){
			for (uint32_t ii = 0; ii < BX_COUNTOF(m_cube_ibh); ++ii)
			{
				bgfx::destroy(m_cube_ibh[ii]);
			}
			bgfx::destroy(m_vbh);
			bgfx::destroy(m_program);
		}
		else if (m_current_example_type == ExampleType::_04_Mesh)
		{
			meshUnload(m_mesh);
			// Cleanup.
			bgfx::destroy(m_program);
			bgfx::destroy(u_time);
		}
		else if (m_current_example_type == ExampleType::_05_Instancing) {
			bgfx::destroy(m_ibh);
			bgfx::destroy(m_program_non_instanced);
			bgfx::destroy(m_vbh);
			bgfx::destroy(m_program);
		}
		else if (m_current_example_type == ExampleType::_10_Font) {
			m_fontManager->destroyTtf(m_fontKenneyTtf);
			m_fontManager->destroyTtf(m_fontAwesomeTtf);
			m_fontManager->destroyTtf(m_visitorTtf);

			// Destroy the fonts.
			m_fontManager->destroyFont(m_fontKenney64);
			m_fontManager->destroyFont(m_fontAwesome72);
			m_fontManager->destroyFont(m_visitor10);
			for (uint32_t ii = 0; ii < numFonts; ++ii)
			{
				m_fontManager->destroyFont(m_fonts[ii]);
			}

			m_textBufferManager->destroyTextBuffer(m_staticText);
			m_textBufferManager->destroyTextBuffer(m_transientText);

			delete m_textBufferManager;
			delete m_fontManager;
		}
		else if (m_current_example_type == ExampleType::_11_Font_sdf) {
			unload(m_txtFile);

			m_fontManager->destroyTtf(m_font);
			// Destroy the fonts.
			m_fontManager->destroyFont(m_fontSdf);
			m_fontManager->destroyFont(m_fontScaled);

			m_textBufferManager->destroyTextBuffer(m_scrollableBuffer);

			delete m_textBufferManager;
			delete m_fontManager;
		}
		else if (m_current_example_type == ExampleType::_30_Picking){
			for (uint32_t ii = 0; ii < 12; ++ii)
			{
				meshUnload(m_meshes[ii]);
			}

			// Cleanup.
			bgfx::destroy(m_shadingProgram);
			bgfx::destroy(m_idProgram);

			bgfx::destroy(u_tint);
			bgfx::destroy(u_id);

			bgfx::destroy(m_pickingFB);
			bgfx::destroy(m_pickingRT);
			bgfx::destroy(m_pickingRTDepth);
			bgfx::destroy(m_blitTex);
		}
		else if (m_current_example_type == ExampleType::_29_Debugdraw) {
			ddDestroy(m_bunny);
			ddDestroy(m_sprite);

			ddShutdown();

			cameraDestroy();
		}
		else if (m_current_example_type == ExampleType::_28_Wireframe) {
			m_wf_meshes[0].destroy();
			m_wf_meshes[1].destroy();
			m_wf_meshes[2].destroy();

			bgfx::destroy(m_wfProgram);
			bgfx::destroy(m_meshProgram);

			m_uniforms.destroy();
		}
		else if (m_current_example_type == ExampleType::_19_Oit) {
			if (bgfx::isValid(m_fbh)){
				bgfx::destroy(m_fbh);
			}

			bgfx::destroy(m_ibh);
			bgfx::destroy(m_vbh);
			bgfx::destroy(m_blend);
			bgfx::destroy(m_wbSeparatePass);
			bgfx::destroy(m_wbSeparateBlit);
			bgfx::destroy(m_wbPass);
			bgfx::destroy(m_wbBlit);
			bgfx::destroy(s_texColor0);
			bgfx::destroy(s_texColor1);
			bgfx::destroy(u_color);
		}
		// Shutdown bgfx.
		bgfx::shutdown();

		return 0;
	}
	void imgui_01_cube_settings() {
		ImGui::SetNextWindowPos(
			ImVec2(m_width - m_width / 5.0f - 10.0f, 10.0f)
			, ImGuiCond_FirstUseEver
		);
		ImGui::SetNextWindowSize(
			ImVec2(m_width / 5.0f, m_height / 3.5f)
			, ImGuiCond_FirstUseEver
		);
		ImGui::Begin("Draw color channel Settings "
			, NULL
			, 0
		);

		ImGui::Checkbox("Write R", &m_r);
		ImGui::Checkbox("Write G", &m_g);
		ImGui::Checkbox("Write B", &m_b);
		ImGui::Checkbox("Write A", &m_a);

		ImGui::Text("Draw graphic element types:");
		ImGui::Combo("##topology", (int*)&m_pt, s_ptNames, BX_COUNTOF(s_ptNames));

		ImGui::End();
	}
	void imgui_05_instanceing() {
		ImGui::SetNextWindowPos(
			ImVec2(m_width - m_width / 5.0f - 10.0f, 10.0f)
			, ImGuiCond_FirstUseEver
		);
		ImGui::SetNextWindowSize(
			ImVec2(m_width / 5.0f, m_height / 2.0f)
			, ImGuiCond_FirstUseEver
		);
		ImGui::Begin("Settings"
			, NULL
			, 0
		);

		// Get renderer capabilities info.
		const bgfx::Caps* caps = bgfx::getCaps();

		// Check if instancing is supported.
		const bool instancingSupported = 0 != (BGFX_CAPS_INSTANCING & caps->supported);
		m_useInstancing &= instancingSupported;

		ImGui::Text("%d draw calls", bgfx::getStats()->numDraw);

		ImGui::PushEnabled(instancingSupported);
		ImGui::Checkbox("Use Instancing", &m_useInstancing);
		ImGui::PopEnabled();

		ImGui::Text("Grid Side Size:");
		ImGui::SliderInt("##size", (int*)&m_sideSize, 1, 512);

		if (m_lastFrameMissing > 0)
		{
			ImGui::TextColored(ImVec4(1.0f, 0.0f, 0.0f, 1.0f), "Couldn't draw %d cubes last frame", m_lastFrameMissing);
		}

		if (bgfx::getStats()->numDraw >= bgfx::getCaps()->limits.maxDrawCalls)
		{
			ImGui::TextColored(ImVec4(1.0f, 0.0f, 0.0f, 1.0f), "Draw call limit reached!");
		}

		ImGui::End();
	}
	void imgui_11_font_sdf() {
		ImGui::SetNextWindowPos(
			ImVec2(m_width - m_width / 5.0f - 10.0f, 10.0f)
			, ImGuiCond_FirstUseEver
		);
		ImGui::SetNextWindowSize(
			ImVec2(m_width / 5.0f, m_height / 2.0f)
			, ImGuiCond_FirstUseEver
		);
		ImGui::Begin("Settings"
			, NULL
			, 0
		);

		bool recomputeVisibleText = false;

		static int fontTypeIndex = 0;
		if (ImGui::Combo("SDF Font Type", &fontTypeIndex, "Standard\0Outline\0Outline_Image\0DropShadow\0DropShadow_Image\0Outline_DropShadow_Image\0\0"))
		{
			uint32_t fontTypeList[] =
			{
				FONT_TYPE_DISTANCE,
				FONT_TYPE_DISTANCE_OUTLINE,
				FONT_TYPE_DISTANCE_OUTLINE_IMAGE,
				FONT_TYPE_DISTANCE_DROP_SHADOW,
				FONT_TYPE_DISTANCE_DROP_SHADOW_IMAGE,
				FONT_TYPE_DISTANCE_OUTLINE_DROP_SHADOW_IMAGE
			};
			uint32_t fontType = fontTypeList[fontTypeIndex];

			initializeFont(fontType);
			initializeTextBuffer(fontType);
			recomputeVisibleText = true;
		}

		if (ImGui::SliderFloat("Font size", &m_textSize, 6.0f, 64.0f))
		{
			m_fontManager->destroyFont(m_fontScaled);
			m_fontScaled = m_fontManager->createScaledFontToPixelSize(m_fontSdf, (uint32_t)m_textSize);
			m_metrics = TextLineMetrics(m_fontManager->getFontInfo(m_fontScaled));
			recomputeVisibleText = true;
		}

		if (ImGui::ColorEdit3("Outline Color", (float*)&m_outlineColor))
		{
			recomputeVisibleText = true;
		}
		if (ImGui::SliderFloat("Outline Width", &m_outlineWidth, 0.5f, 5.0f))
		{
			recomputeVisibleText = true;
		}
		if (ImGui::ColorEdit4("Drop Shadow Color", (float*)&m_dropShadowColor))
		{
			recomputeVisibleText = true;
		}
		if (ImGui::SliderFloat("Drop Shadow Offset X", &m_dropShadowOffsetX, -5.0f, 5.0f))
		{
			recomputeVisibleText = true;
		}
		if (ImGui::SliderFloat("Drop Shadow Offset Y", &m_dropShadowOffsetY, -5.0f, 5.0f))
		{
			recomputeVisibleText = true;
		}
		if (ImGui::SliderFloat("Drop Shadow Softener", &m_dropShadowSoftener, 0.0f, 5.0f))
		{
			recomputeVisibleText = true;
		}

		recomputeVisibleText |= ImGui::SliderFloat("# of lines", &m_visibleLineCount, 1.0f, 177.0f);
		recomputeVisibleText |= ImGui::SliderFloat("Scroll", &m_textScroll, 0.0f, (m_lineCount - m_visibleLineCount));
		ImGui::SliderFloat("Rotate", &m_textRotation, 0.0f, bx::kPi * 2.0f);
		recomputeVisibleText |= ImGui::SliderFloat("Scale", &m_textScale, 0.1f, 10.0f);

		if (recomputeVisibleText)
		{
			m_textBufferManager->clearTextBuffer(m_scrollableBuffer);

			applyTextBufferAttributes();

			m_metrics.getSubText(m_bigText, (uint32_t)m_textScroll, (uint32_t)(m_textScroll + m_visibleLineCount), m_textBegin, m_textEnd);
			m_textBufferManager->appendText(m_scrollableBuffer, m_fontScaled, m_textBegin, m_textEnd);
		}

		ImGui::End();
	}
#pragma region 29-debugdraw
	template<typename Ty>
	bool intersect(DebugDrawEncoder* _dde, const bx::Ray& _ray, const Ty& _shape)
	{
		bx::Hit hit;
		if (bx::intersect(_ray, _shape, &hit))
		{
			_dde->push();

			_dde->setWireframe(false);

			_dde->setColor(0xff0000ff);

			_dde->drawCone(hit.pos, bx::mad(hit.plane.normal, 0.7f, hit.pos), 0.1f);

			_dde->pop();

			return true;
		}

		return false;
	}
	float timeScale = 1.0f;
	float amplitudeMul = 0.0f;
	void imgui_29_debugdraw() {
		ImGui::SetNextWindowPos(
			ImVec2(m_width - m_width / 5.0f - 10.0f, 10.0f)
			, ImGuiCond_FirstUseEver
		);
		ImGui::SetNextWindowSize(
			ImVec2(m_width / 5.0f, m_height / 3.0f)
			, ImGuiCond_FirstUseEver
		);
		ImGui::Begin("Settings"
			, NULL
			, 0
		);
		ImGui::SliderFloat("Amplitude", &amplitudeMul, 0.0f, 1.0f);
		ImGui::SliderFloat("T scale", &timeScale, -1.0f, 1.0f);

		ImGui::End();
	}
#pragma endregion
	void imgui_28_wireframe() {
		ImGui::SetNextWindowPos(
			ImVec2(m_width - m_width / 5.0f - 10.0f, 10.0f)
			, ImGuiCond_FirstUseEver
		);
		ImGui::SetNextWindowSize(
			ImVec2(m_width / 5.0f, m_height * 0.75f)
			, ImGuiCond_FirstUseEver
		);
		ImGui::Begin("Settings"
			, NULL
			, 0
		);

		ImGui::Separator();
		ImGui::Text("Draw mode:");
		ImGui::RadioButton("Wireframe + Shaded", &m_drawMode, 0);
		ImGui::RadioButton("Wireframe", &m_drawMode, 1);
		ImGui::RadioButton("Shaded", &m_drawMode, 2);

		const bool wfEnabled = (DrawMode::Shaded != m_drawMode);
		if (wfEnabled)
		{
			ImGui::Separator();

			ImGui::ColorWheel("Color", m_uniforms.m_wfColor, 0.6f);
			ImGui::SliderFloat("Thickness", &m_uniforms.m_wfThickness, 0.6f, 2.2f);
		}

		ImGui::Separator();
		ImGui::Text("Mesh:");
		{
			bool meshChanged = false;
			meshChanged |= ImGui::RadioButton("Bunny", &m_meshSelection, 0);
			meshChanged |= ImGui::RadioButton("Hollowcubes", &m_meshSelection, 1);
			meshChanged |= ImGui::RadioButton("Orb", &m_meshSelection, 2);

			if (meshChanged)
			{
				m_camera.reset();
			}
		}

		ImGui::End();
	}
	bool update() override
	{
		if (!entry::processEvents(m_width, m_height, m_debug, m_reset, &m_mouseState) )
		{
			if (m_current_example_type == ExampleType::_28_Wireframe){
				if (m_oldWidth != m_width
					|| m_oldHeight != m_height
					|| m_oldReset != m_reset){
					// Recreate variable size render targets when resolution changes.
					m_oldWidth = m_width;
					m_oldHeight = m_height;
					m_oldReset = m_reset;
				}
			}
			imguiBeginFrame(m_mouseState.m_mx
				,  m_mouseState.m_my
				, (m_mouseState.m_buttons[entry::MouseButton::Left  ] ? IMGUI_MBUT_LEFT   : 0)
				| (m_mouseState.m_buttons[entry::MouseButton::Right ] ? IMGUI_MBUT_RIGHT  : 0)
				| (m_mouseState.m_buttons[entry::MouseButton::Middle] ? IMGUI_MBUT_MIDDLE : 0)
				,  m_mouseState.m_mz
				, uint16_t(m_width)
				, uint16_t(m_height)
				);
			const bgfx::Caps* caps = bgfx::getCaps();
			bool blitSupport = false;
			if (!(m_current_example_type == ExampleType::_30_Picking || m_current_example_type == ExampleType::_19_Oit)){
				showExampleDialog(this);
			}
			if (m_current_example_type == ExampleType::_01_Cubes){
				imgui_01_cube_settings();
			}
			else if (m_current_example_type == ExampleType::_05_Instancing) {
				imgui_05_instanceing();
			}
			else if (m_current_example_type == ExampleType::_11_Font_sdf) {
				imgui_11_font_sdf();
			}
			else if (m_current_example_type == ExampleType::_30_Picking) {
				blitSupport = 0 != (caps->supported & BGFX_CAPS_TEXTURE_BLIT);
				showExampleDialog(this
					, !blitSupport
					? "BGFX_CAPS_TEXTURE_BLIT is not supported."
					: NULL
				);
				if (true)
				{
					ImGui::SetNextWindowPos(
						ImVec2(m_width - m_width / 5.0f - 10.0f, 10.0f)
						, ImGuiCond_FirstUseEver
					);
					ImGui::SetNextWindowSize(
						ImVec2(m_width / 5.0f, m_height / 2.0f)
						, ImGuiCond_FirstUseEver
					);
					ImGui::Begin("Settings"
						, NULL
						, 0
					);

					ImGui::Image(m_pickingRT, ImVec2(m_width / 5.0f - 16.0f, m_width / 5.0f - 16.0f));
					ImGui::SliderFloat("Field of view", &m_fov, 1.0f, 60.0f);
					ImGui::Checkbox("Spin Camera", &m_cameraSpin);

					ImGui::End();
				}
			}
			else if (m_current_example_type == ExampleType::_29_Debugdraw){
				imgui_29_debugdraw();
			}
			else if (m_current_example_type == ExampleType::_28_Wireframe){
				imgui_28_wireframe();
			}
			else if (m_current_example_type == ExampleType::_19_Oit) {
				showExampleDialog(this
					, !m_mrtSupported
					? "MRT or frame buffer texture format are not supported."
					: NULL
				);
				if (m_mrtSupported){
					if (m_oldWidth != m_width
						|| m_oldHeight != m_height
						|| m_oldReset != m_reset
						|| !bgfx::isValid(m_fbh)){
						// Recreate variable size render targets when resolution changes.
						m_oldWidth = m_width;
						m_oldHeight = m_height;
						m_oldReset = m_reset;

						if (bgfx::isValid(m_fbh))
						{
							bgfx::destroy(m_fbh);
						}

						m_fbtextures[0] = bgfx::createTexture2D(uint16_t(m_width), uint16_t(m_height), false, 1, bgfx::TextureFormat::RGBA16F, BGFX_TEXTURE_RT);
						m_fbtextures[1] = bgfx::createTexture2D(uint16_t(m_width), uint16_t(m_height), false, 1, bgfx::TextureFormat::R16F, BGFX_TEXTURE_RT);
						m_fbh = bgfx::createFrameBuffer(BX_COUNTOF(m_fbtextures), m_fbtextures, true);
					}

					ImGui::SetNextWindowPos(
						ImVec2(m_width - m_width / 5.0f - 10.0f, 10.0f)
						, ImGuiCond_FirstUseEver
					);
					ImGui::SetNextWindowSize(
						ImVec2(m_width / 5.0f, m_height / 3.0f)
						, ImGuiCond_FirstUseEver
					);
					ImGui::Begin("Settings"
						, NULL
						, 0
					);

					ImGui::Separator();

					ImGui::Text("Blend mode:");

					ImGui::RadioButton("None", &m_mode, 0);
					ImGui::RadioButton("Separate", &m_mode, 1);
					ImGui::RadioButton("MRT Independent", &m_mode, 2);

					ImGui::Separator();

					ImGui::Checkbox("Front to back", &m_frontToBack);
					ImGui::Checkbox("Fade in/out", &m_fadeInOut);

					ImGui::End();
				}
			}
			imguiEndFrame();

			float time = (float)( (bx::getHPCounter()-m_timeOffset)/double(bx::getHPFrequency() ) );
#pragma region _30_Picking
			const float camSpeed = 0.25;
			float cameraSpin = (float)m_cameraSpin;
			float eyeDist = 2.5f;
#pragma endregion
#pragma region 29-debugdraw
			int64_t now = bx::getHPCounter() - m_timeOffset;
			static int64_t last = now;
			const int64_t frameTime = now - last;
			last = now;
			const double freq = double(bx::getHPFrequency());
			const float deltaTime = float(frameTime / freq);
			if (m_current_example_type == ExampleType::_29_Debugdraw) {
				// Update camera.
				cameraUpdate(deltaTime, m_mouseState, ImGui::MouseOverArea());
			}
#pragma endregion

			if (m_current_example_type == ExampleType::_05_Instancing){
				if (!m_useInstancing){
					// When instancing is not supported by GPU, implement alternative
					// code path that doesn't use instancing.
					bool blink = uint32_t(time * 3.0f) & 1;
					bgfx::dbgTextPrintf(0, 0, blink ? 0x4f : 0x04, " Instancing is not supported by GPU. ");
					m_useInstancing = false;
				}
			}
			bx::Vec3 at  = { 0.0f, 0.0f,   0.0f };
			bx::Vec3 eye = { 0.0f, 0.0f, -35.0f };
			if (m_current_example_type == ExampleType::_04_Mesh){
				at = { 0.0f, 1.0f,  0.0f };
				eye = { 0.0f, 1.0f, -2.5f };
			}else if (m_current_example_type == ExampleType::_11_Font_sdf) {
				at = { 0.0f, 0.0f,  0.0f };
				eye = { 0.0f, 0.0f, -1.0f };
			}else if (m_current_example_type == ExampleType::_30_Picking) {
				// Set up matrices for basic forward renderer
				at = { 0.0f, 0.0f, 0.0f };
				eye =
				{
					-eyeDist * bx::sin(time * cameraSpin * camSpeed),
					0.0f,
					-eyeDist * bx::cos(time * cameraSpin * camSpeed),
				};
			}
			// Set view and projection matrix for view 0.
			float view[16];
			float proj[16];
			{
				if (m_current_example_type == ExampleType::_29_Debugdraw) {
					cameraGetViewMtx(view);
				}
				else {
					bx::mtxLookAt(view, eye, at);
				}
				bx::mtxProj(proj, 60.0f, float(m_width)/float(m_height), 0.1f, 100.0f, caps->homogeneousDepth);
				// Set view 0 (view, proj)
				bgfx::setViewTransform(0, view, proj);
				// Set view 0 default viewport.
				bgfx::setViewRect(0, 0, 0, uint16_t(m_width), uint16_t(m_height) );
			}

			// This dummy draw call is here to make sure that view 0 is cleared
			// if no other draw calls are submitted to view 0.
			bgfx::touch(0);
			if (m_current_example_type == ExampleType::_01_Cubes) {
				bgfx::IndexBufferHandle ibh = m_cube_ibh[m_pt];
				uint64_t state = 0
					| (m_r ? BGFX_STATE_WRITE_R : 0)
					| (m_g ? BGFX_STATE_WRITE_G : 0)
					| (m_b ? BGFX_STATE_WRITE_B : 0)
					| (m_a ? BGFX_STATE_WRITE_A : 0)
					| BGFX_STATE_WRITE_Z
					| BGFX_STATE_DEPTH_TEST_LESS
					| BGFX_STATE_CULL_CW
					| BGFX_STATE_MSAA
					| s_ptState[m_pt]
					;

				// Submit 11x11 cubes.
				for (uint32_t yy = 0; yy < 11; ++yy)
				{
					for (uint32_t xx = 0; xx < 11; ++xx)
					{
						float mtx[16];
						bx::mtxRotateXY(mtx, time + xx * 0.21f, time + yy * 0.37f);
						mtx[12] = -15.0f + float(xx) * 3.0f;
						mtx[13] = -15.0f + float(yy) * 3.0f;
						mtx[14] = 0.0f;

						// Set model matrix for rendering.
						bgfx::setTransform(mtx);

						// Set vertex and index buffer.
						bgfx::setVertexBuffer(0, m_vbh);
						bgfx::setIndexBuffer(ibh);

						// Set render states.
						bgfx::setState(state);

						// Submit primitive for rendering to view 0.
						bgfx::submit(0, m_program);
					}
				}
			}
			else if (m_current_example_type == ExampleType::_04_Mesh) {
				bgfx::setUniform(u_time, &time);
				float mtx[16];
				bx::mtxRotateXY(mtx
					, 0.0f
					, time * 0.37f
				);
				meshSubmit(m_mesh, 0, m_program, mtx);
			}
			else if (m_current_example_type == ExampleType::_05_Instancing) {
				m_lastFrameMissing = 0;
				if (m_useInstancing){
					// 80 bytes stride = 64 bytes for 4x4 matrix + 16 bytes for RGBA color.
					const uint16_t instanceStride = 80;
					// to total number of instances to draw
					uint32_t totalCubes = m_sideSize * m_sideSize;

					// figure out how big of a buffer is available
					uint32_t drawnCubes = bgfx::getAvailInstanceDataBuffer(totalCubes, instanceStride);

					// save how many we couldn't draw due to buffer room so we can display it
					m_lastFrameMissing = totalCubes - drawnCubes;

					bgfx::InstanceDataBuffer idb;
					bgfx::allocInstanceDataBuffer(&idb, drawnCubes, instanceStride);

					uint8_t* data = idb.data;

					for (uint32_t ii = 0; ii < drawnCubes; ++ii)
					{
						uint32_t yy = ii / m_sideSize;
						uint32_t xx = ii % m_sideSize;

						float* mtx = (float*)data;
						bx::mtxRotateXY(mtx, time + xx * 0.21f, time + yy * 0.37f);
						mtx[12] = -15.0f + float(xx) * 3.0f;
						mtx[13] = -15.0f + float(yy) * 3.0f;
						mtx[14] = 0.0f;

						float* color = (float*)&data[64];
						color[0] = bx::sin(time + float(xx) / 11.0f) * 0.5f + 0.5f;
						color[1] = bx::cos(time + float(yy) / 11.0f) * 0.5f + 0.5f;
						color[2] = bx::sin(time * 3.0f) * 0.5f + 0.5f;
						color[3] = 1.0f;

						data += instanceStride;
					}

					// Set vertex and index buffer.
					bgfx::setVertexBuffer(0, m_vbh);
					bgfx::setIndexBuffer(m_ibh);

					// Set instance data buffer.
					bgfx::setInstanceDataBuffer(&idb);

					// Set render states.
					bgfx::setState(BGFX_STATE_DEFAULT);

					// Submit primitive for rendering to view 0.
					bgfx::submit(0, m_program);
				}
				else{// non-instanced path// not look
					for (uint32_t yy = 0; yy < m_sideSize; ++yy){
						for (uint32_t xx = 0; xx < m_sideSize; ++xx)	{
							float mtx[16];
							bx::mtxRotateXY(mtx, time + xx * 0.21f, time + yy * 0.37f);
							mtx[12] = -15.0f + float(xx) * 3.0f;
							mtx[13] = -15.0f + float(yy) * 3.0f;
							mtx[14] = 0.0f;

							// Set model matrix for rendering.
							bgfx::setTransform(mtx);

							// Set vertex and index buffer.
							bgfx::setVertexBuffer(0, m_vbh);
							bgfx::setIndexBuffer(m_ibh);

							// Set render states.
							bgfx::setState(BGFX_STATE_DEFAULT);

							// Submit primitive for rendering to view 0.
							bgfx::submit(0, m_program_non_instanced);
						}
					}
				}
			}
			else if (m_current_example_type == ExampleType::_10_Font){
				const double freq = double(bx::getHPFrequency());
				const double toMs = 1000.0 / freq;

				// Use transient text to display debug information.
				char fpsText[64];
				bx::snprintf(fpsText, BX_COUNTOF(fpsText), "Frame: % 7.3f[ms]", double(frameTime)* toMs);

				m_textBufferManager->clearTextBuffer(m_transientText);
				m_textBufferManager->setPenPosition(m_transientText, m_width - 150.0f, 10.0f);
				m_textBufferManager->appendText(m_transientText, m_visitor10, "Transient\n");
				m_textBufferManager->appendText(m_transientText, m_visitor10, "text buffer\n");
				m_textBufferManager->appendText(m_transientText, m_visitor10, fpsText);

				const bx::Vec3 at = { 0.0f, 0.0f,  0.0f };
				const bx::Vec3 eye = { 0.0f, 0.0f, -1.0f };

				float view[16];
				bx::mtxLookAt(view, eye, at);

				// Setup a top-left ortho matrix for screen space drawing.
				const bgfx::Caps* caps = bgfx::getCaps();
				{
					float ortho[16];
					bx::mtxOrtho(
						ortho
						, 0.0f
						, float(m_width)
						, float(m_height)
						, 0.0f
						, 0.0f
						, 100.0f
						, 0.0f
						, caps->homogeneousDepth
					);
					bgfx::setViewTransform(0, view, ortho);
					bgfx::setViewRect(0, 0, 0, uint16_t(m_width), uint16_t(m_height));
				}

				// Submit the debug text.
				m_textBufferManager->submitTextBuffer(m_transientText, 0);

				// Submit the static text.
				m_textBufferManager->submitTextBuffer(m_staticText, 0);
			}
			else if (m_current_example_type == ExampleType::_11_Font_sdf) {
			    const bgfx::Caps* caps = bgfx::getCaps();

				float view[16];
				bx::mtxLookAt(view, eye, at);
				float ortho[16];
				bx::mtxOrtho(ortho, 0.0f, float(m_width), float(m_height), 0.0f, -1.0f, 1.0f, 0.0f, caps->homogeneousDepth);
				bgfx::setViewTransform(0, view, ortho);
				bgfx::setViewRect(0, 0, 0, uint16_t(m_width), uint16_t(m_height));

				//very crude approximation :(
				float textAreaWidth = 0.5f * 66.0f * m_fontManager->getFontInfo(m_fontScaled).maxAdvanceWidth;

				float textRotMat[16];
				float textCenterMat[16];
				float textScaleMat[16];
				float screenCenterMat[16];

				bx::mtxRotateZ(textRotMat, m_textRotation);
				bx::mtxTranslate(textCenterMat, -(textAreaWidth * 0.5f), (-m_visibleLineCount)* m_metrics.getLineHeight() * 0.5f, 0);
				bx::mtxScale(textScaleMat, m_textScale, m_textScale, 1.0f);
				bx::mtxTranslate(screenCenterMat, ((m_width) * 0.5f), ((m_height) * 0.5f), 0);

				//first translate to text center, then scale, then rotate
				float tmpMat[16];
				bx::mtxMul(tmpMat, textCenterMat, textRotMat);

				float tmpMat2[16];
				bx::mtxMul(tmpMat2, tmpMat, textScaleMat);

				float tmpMat3[16];
				bx::mtxMul(tmpMat3, tmpMat2, screenCenterMat);

				// Set model matrix for rendering.
				bgfx::setTransform(tmpMat3);

				// Draw your text.
				m_textBufferManager->submitTextBuffer(m_scrollableBuffer, 0);
            }
			else if (m_current_example_type == ExampleType::_30_Picking){
			    bgfx::setViewFrameBuffer(RENDER_PASS_ID, m_pickingFB);//very import
				// Set up picking pass
				float viewProj[16];
				bx::mtxMul(viewProj, view, proj);
				float invViewProj[16];
				bx::mtxInverse(invViewProj, viewProj);

				// Mouse coord in NDC
				float mouseXNDC = (m_mouseState.m_mx / (float)m_width) * 2.0f - 1.0f;
				float mouseYNDC = ((m_height - m_mouseState.m_my) / (float)m_height) * 2.0f - 1.0f;

				const bx::Vec3 pickEye = bx::mulH({ mouseXNDC, mouseYNDC, 0.0f }, invViewProj);
				const bx::Vec3 pickAt = bx::mulH({ mouseXNDC, mouseYNDC, 1.0f }, invViewProj);

				// Look at our unprojected point
				float pickView[16];
				bx::mtxLookAt(pickView, pickEye, pickAt);

				// Tight FOV is best for picking
				float pickProj[16];
				bx::mtxProj(pickProj, m_fov, 1, 0.1f, 100.0f, caps->homogeneousDepth);

				// View rect and transforms for picking pass
				bgfx::setViewRect(RENDER_PASS_ID, 0, 0, ID_DIM, ID_DIM);
				bgfx::setViewTransform(RENDER_PASS_ID, pickView, pickProj);

				// Now that our passes are set up, we can finally draw each mesh

				// Picking highlights a mesh so we'll set up this tint color
				const float tintBasic[4] = { 1.0f, 1.0f, 1.0f, 1.0f };
				const float tintHighlighted[4] = { 0.3f, 0.3f, 2.0f, 1.0f };

				for (uint32_t mesh = 0; mesh < 12; ++mesh){
					const float scale = m_meshScale[mesh];

					// Set up transform matrix for each mesh
					float mtx[16];
					bx::mtxSRT(mtx
						, scale, scale, scale
						, 0.0f
						, time * 0.37f * (mesh % 2 ? 1.0f : -1.0f)
						, 0.0f
						, (mesh % 4) - 1.5f
						, (mesh / 4) - 1.25f
						, 0.0f
					);

					// Submit mesh to both of our render passes
					// Set uniform based on if this is the highlighted mesh
					bgfx::setUniform(u_tint
						, mesh == m_highlighted
						? tintHighlighted
						: tintBasic
					);
					meshSubmit(m_meshes[mesh], RENDER_PASS_SHADING, m_shadingProgram, mtx);

					// Submit ID pass based on mesh ID
					bgfx::setUniform(u_id, m_idsF[mesh]);
					meshSubmit(m_meshes[mesh], RENDER_PASS_ID, m_idProgram, mtx);
				}

				// If the user previously clicked, and we're done reading data from GPU, look at ID buffer on CPU
				// Whatever mesh has the most pixels in the ID buffer is the one the user clicked on.
				if (m_reading == m_currFrame){
					m_reading = 0;
					std::map<uint32_t, uint32_t> ids;  // This contains all the IDs found in the buffer
					uint32_t maxAmount = 0;
					for (uint8_t* x = m_blitData; x < m_blitData + ID_DIM * ID_DIM * 4;){
						uint8_t rr = *x++;
						uint8_t gg = *x++;
						uint8_t bb = *x++;
						uint8_t aa = *x++;

						if (0 == (rr | gg | bb)) {// Skip background
							continue;
						}

						uint32_t hashKey = rr + (gg << 8) + (bb << 16) + (aa << 24);
						std::map<uint32_t, uint32_t>::iterator mapIter = ids.find(hashKey);
						uint32_t amount = 1;
						if (mapIter != ids.end()){
							amount = mapIter->second + 1;
						}

						ids[hashKey] = amount; // Amount of times this ID (color) has been clicked on in buffer
						maxAmount = maxAmount > amount
							? maxAmount
							: amount
							;
					}
					uint32_t idKey = 0;
					m_highlighted = UINT32_MAX;
					if (maxAmount){
						for (std::map<uint32_t, uint32_t>::iterator mapIter = ids.begin(); mapIter != ids.end(); mapIter++){
							if (mapIter->second == maxAmount)
							{
								idKey = mapIter->first;
								break;
							}
						}
						for (uint32_t ii = 0; ii < 12; ++ii){
							if (m_idsU[ii] == idKey){
								m_highlighted = ii;
								break;
							}
						}
					}
				}
				// Start a new readback?
				if (!m_reading
					&& m_mouseState.m_buttons[entry::MouseButton::Left]){
					// Blit and read
					bgfx::blit(RENDER_PASS_BLIT, m_blitTex, 0, 0, m_pickingRT);
					m_reading = bgfx::readTexture(m_blitTex, m_blitData);
				}
			}
			else if (m_current_example_type == ExampleType::_29_Debugdraw){
				float mtxVp[16];
				float mtxInvVp[16];
				bx::mtxMul(mtxVp, view, proj);
				bx::mtxInverse(mtxInvVp, mtxVp);

				const bx::Vec3 at = { 0.0f,  0.0f, 0.0f };
				const bx::Vec3 eye = { 5.0f, 10.0f, 5.0f };
				bx::mtxLookAt(view, eye, at);
				bx::mtxProj(proj, 45.0f, float(m_width) / float(m_height), 1.0f, 15.0f, bgfx::getCaps()->homogeneousDepth);
				bx::mtxMul(mtxVp, view, proj);

				bx::Ray ray = bx::makeRay(
					(float(m_mouseState.m_mx) / float(m_width) * 2.0f - 1.0f)
					, -(float(m_mouseState.m_my) / float(m_height) * 2.0f - 1.0f)
					, mtxInvVp
				);

				constexpr uint32_t kSelected = 0xff80ffff;
				constexpr uint32_t kOverlapA = 0xff0000ff;
				constexpr uint32_t kOverlapB = 0xff8080ff;

				DebugDrawEncoder dde;

				dde.begin(0);
				dde.drawAxis(0.0f, 0.0f, 0.0f);

				dde.push();
				bx::Aabb aabb =
				{
					{  5.0f, 1.0f, 1.0f },
					{ 10.0f, 5.0f, 5.0f },
				};
				dde.setWireframe(true);
				dde.setColor(intersect(&dde, ray, aabb) ? kSelected : 0xff00ff00);
				dde.draw(aabb);
				dde.pop();

				static float time = 0.0f;
				time += deltaTime * timeScale;

				bx::Obb obb;
				bx::mtxRotateX(obb.mtx, time);
				dde.setWireframe(true);
				dde.setColor(intersect(&dde, ray, obb) ? kSelected : 0xffffffff);
				dde.draw(obb);

				bx::mtxSRT(obb.mtx, 1.0f, 1.0f, 1.0f, time * 0.23f, time, 0.0f, 3.0f, 0.0f, 0.0f);

				dde.push();
				bx::toAabb(aabb, obb);
				dde.setWireframe(true);
				dde.setColor(0xff0000ff);
				dde.draw(aabb);
				dde.pop();

				dde.setWireframe(false);
				dde.setColor(intersect(&dde, ray, obb) ? kSelected : 0xffffffff);
				dde.draw(obb);

				dde.setColor(0xffffffff);

				dde.push();
				{
					float bunny[16];
					bx::mtxSRT(bunny, 0.03f, 0.03f, 0.03f, 0.0f, 0.0f, 0.0f, -3.0f, 0.0f, 0.0f);

					dde.setTransform(bunny);
					const bool wireframe = bx::mod(time, 2.0f) > 1.0f;
					dde.setWireframe(wireframe);
					dde.setColor(wireframe ? 0xffff00ff : 0xff00ff00);
					dde.draw(m_bunny);
					dde.setTransform(NULL);
				}
				dde.pop();

				{
					const bx::Vec3 normal = { 0.0f,  1.0f, 0.0f };
					const bx::Vec3 pos = { 0.0f, -2.0f, 0.0f };

					bx::Plane plane(bx::InitNone);
					bx::calcPlane(plane, normal, pos);

					dde.setColor(false|| intersect(&dde, ray, plane)
						? kSelected
						: 0xffffffff
					);

					dde.drawGrid(Axis::Y, pos, 128, 1.0f);
				}

				dde.drawFrustum(mtxVp);

				dde.push();
				bx::Sphere sphere = { { 0.0f, 5.0f, 0.0f }, 1.0f };
				dde.setColor(intersect(&dde, ray, sphere) ? kSelected : 0xfff0c0ff);
				dde.setWireframe(true);
				dde.setLod(3);
				dde.draw(sphere);
				dde.setWireframe(false);

				sphere.center.x = -2.0f;
				dde.setColor(intersect(&dde, ray, sphere) ? kSelected : 0xc0ffc0ff);
				dde.setLod(2);
				dde.draw(sphere);

				sphere.center.x = -4.0f;
				dde.setColor(intersect(&dde, ray, sphere) ? kSelected : 0xa0f0ffff);
				dde.setLod(1);
				dde.draw(sphere);

				sphere.center.x = -6.0f;
				dde.setColor(intersect(&dde, ray, sphere) ? kSelected : 0xffc0ff00);
				dde.setLod(0);
				dde.draw(sphere);
				dde.pop();

				dde.setColor(0xffffffff);

				dde.push();
				{
					const bx::Vec3 normal = { 0.0f, 0.0f, 1.0f };
					const bx::Vec3 center = { -8.0f, 0.0f, 0.0f };
					dde.push();
					dde.setStipple(true, 1.0f, time * 0.1f);
					dde.setColor(0xff0000ff);
					dde.drawCircle(normal, center, 1.0f, 0.5f + bx::sin(time * 10.0f));
					dde.pop();

					dde.setSpin(time);
					dde.drawQuad(m_sprite, normal, center, 2.0f);
				}
				dde.pop();

				dde.push();
				dde.setStipple(true, 1.0f, -time * 0.1f);
				dde.drawCircle(Axis::Z, -8.0f, 0.0f, 0.0f, 1.25f, 2.0f);
				dde.pop();

				dde.push();
				dde.setLod(UINT8_MAX);

				dde.push();
				dde.setSpin(time * 0.3f);
				{
					bx::Cone cone =
					{
						{ -11.0f, 4.0f,  0.0f },
						{ -13.0f, 6.0f,  1.0f },
						1.0f
					};

					bx::Cylinder cylinder =
					{
						{  -9.0f, 2.0f, -1.0f },
						{ -11.0f, 4.0f,  0.0f },
						0.5f
					};

					dde.setColor(false
						|| intersect(&dde, ray, cone)
						|| intersect(&dde, ray, cylinder)
						? kSelected
						: 0xffffffff
					);

					dde.draw(cone);
					dde.draw(cylinder);
				}
				dde.pop();

				{
					dde.setLod(0);
					bx::Capsule capsule =
					{
						{  0.0f, 7.0f, 0.0f },
						{ -6.0f, 7.0f, 0.0f },
						0.5f
					};
					dde.setColor(intersect(&dde, ray, capsule) ? kSelected : 0xffffffff);
					dde.draw(capsule);
				}
				dde.pop();

				dde.push();

				float mtx[16];
				bx::mtxSRT(mtx
					, 1.0f, 1.0f, 1.0f
					, 0.0f, time, time * 0.53f
					, -10.0f, 1.0f, 10.0f
				);

				bx::Cylinder cylinder =
				{
					{ -10.0f, 1.0f, 10.0f },
					{   0.0f, 0.0f,  0.0f },
					1.0f
				};

				cylinder.end = bx::mul({ 0.0f, 4.0f, 0.0f }, mtx);
				dde.setColor(intersect(&dde, ray, cylinder) ? kSelected : 0xffffffff);
				dde.draw(cylinder);

				dde.push();
				toAabb(aabb, cylinder);
				dde.setWireframe(true);
				dde.setColor(0xff0000ff);
				dde.draw(aabb);
				dde.pop();

				dde.pop();

				dde.drawOrb(-11.0f, 0.0f, 0.0f, 1.0f);

				dde.push();
				{
					constexpr uint32_t colorA[] =
					{
						0xffffffff,
						kOverlapA,
						0xff666666,
						0xff6666ff,
					};

					constexpr uint32_t colorB[] =
					{
						0xffffffff,
						kOverlapB,
						0xff888888,
						0xff8888ff,
					};

					constexpr float kStep = 3.0f;

					bx::Vec3 posA =
					{
						-4.5f * kStep,
						 1.0f,
						20.0f,
					};

					for (uint32_t ii = 0; ii < Shape::Type::Count; ++ii)
					{
						const bx::Vec3 posB = bx::add(posA,
							{
								amplitudeMul * bx::sin(time * 0.39f) * 1.03f,
								amplitudeMul * bx::cos(time * 0.79f) * 1.03f,
								amplitudeMul * bx::cos(time) * 1.03f,
							});

						for (uint32_t jj = 0; jj < Shape::Type::Count; ++jj)
						{
							const bx::Vec3 pa = bx::add(posA, { jj * kStep, 0.0f, 0.0f });
							const bx::Vec3 pb = bx::add(posB, { jj * kStep, 0.0f, 0.0f });

							Shape shapeA, shapeB;
							initA(shapeA, Shape::Type::Enum(ii), pa);
							initB(shapeB, Shape::Type::Enum(jj), pb);

							int32_t olp = overlap(shapeA, shapeB);

							dde.setColor(colorA[olp]);
							dde.setWireframe(false);
							draw(dde, shapeA, pa);

							dde.setColor(colorB[olp]);
							dde.setWireframe(true);
							draw(dde, shapeB, pb);
						}

						posA = bx::add(posA, { 0.0f, 0.0f, kStep });
					}
				}

				dde.pop();

				dde.end();
			}
			else if (m_current_example_type == ExampleType::_28_Wireframe){
				const float deltaTimeSec = float(double(frameTime) / freq);
				// Setup view.
				//bgfx::setViewRect(0, 0, 0, bgfx::BackbufferRatio::Equal); // Equal to backbuffer.

				const bool mouseOverGui = ImGui::MouseOverArea();
				m_mouse.update(float(m_mouseState.m_mx), float(m_mouseState.m_my), m_mouseState.m_mz, m_width, m_height);
				if (!mouseOverGui){
					if (m_mouseState.m_buttons[entry::MouseButton::Left]){
						m_camera.orbit(m_mouse.m_dx, m_mouse.m_dy);
					}
					else if (m_mouseState.m_buttons[entry::MouseButton::Right])
					{
						m_camera.dolly(m_mouse.m_dx + m_mouse.m_dy);
					}
					else if (0 != m_mouse.m_scroll){
						m_camera.dolly(float(m_mouse.m_scroll) * 0.1f);
					}
				}

				m_camera.update(deltaTimeSec);
				bx::memCopy(m_uniforms.m_camPos, &m_camera.m_pos.curr.x, 3 * sizeof(float));
				m_camera.mtxLookAt(view);
				bx::mtxProj(proj, 60.0f, float(m_width) / float(m_height), 0.1f, 100.0f, bgfx::getCaps()->homogeneousDepth);
				bgfx::setViewTransform(0, view, proj);

				m_uniforms.m_drawEdges = (DrawMode::WireframeShaded == m_drawMode) ? 1.0f : 0.0f;
				m_uniforms.submit();
				if (DrawMode::Wireframe == m_drawMode){
					uint64_t state = 0
						| BGFX_STATE_WRITE_RGB
						| BGFX_STATE_WRITE_A
						| BGFX_STATE_WRITE_Z
						| BGFX_STATE_CULL_CCW
						| BGFX_STATE_MSAA
						| BGFX_STATE_BLEND_FUNC(BGFX_STATE_BLEND_SRC_ALPHA, BGFX_STATE_BLEND_INV_SRC_ALPHA)
						;
					meshSubmit(m_wf_meshes[m_meshSelection].m_mesh, 0, m_wfProgram, m_wf_meshes[m_meshSelection].m_mtx, state);
				}
				else{
					uint64_t state = 0
						| BGFX_STATE_WRITE_RGB
						| BGFX_STATE_WRITE_A
						| BGFX_STATE_DEPTH_TEST_LESS
						| BGFX_STATE_WRITE_Z
						| BGFX_STATE_CULL_CCW
						| BGFX_STATE_MSAA
						;
					meshSubmit(m_wf_meshes[m_meshSelection].m_mesh, 0, m_meshProgram, m_wf_meshes[m_meshSelection].m_mtx, state);
				}
			}
			else if (m_current_example_type == ExampleType::_19_Oit){
				// Set view 0 default viewport.
				//bgfx::setViewRect(0, 0, 0, uint16_t(m_width), uint16_t(m_height));
				bgfx::setViewRect(1, 0, 0, uint16_t(m_width), uint16_t(m_height));
				float time = (float)((now - m_timeOffset) / freq);

				// Reference(s):
				// - Weighted, Blended Order-Independent Transparency
				//   https://web.archive.org/save/http://jcgt.org/published/0002/02/09/
				//   https://web.archive.org/web/20181126040455/http://casual-effects.blogspot.com/2014/03/weighted-blended-order-independent.html
				//
				at = { 0.0f, 0.0f,  0.0f };
				eye = { 0.0f, 0.0f, -7.0f };

				// Set view and projection matrix for view 0.
				bx::mtxLookAt(view, eye, at);
				mtxProj(proj, 60.0f, float(m_width) / float(m_height), 0.1f, 100.0f);

				bgfx::setViewTransform(0, view, proj);
				// Set palette color for index 0
				bgfx::setPaletteColor(0, 0.0f, 0.0f, 0.0f, 0.0f);
				// Set palette color for index 1
				bgfx::setPaletteColor(1, 1.0f, 1.0f, 1.0f, 1.0f);

				bgfx::setViewClear(0
					, BGFX_CLEAR_COLOR | BGFX_CLEAR_DEPTH
					, 1.0f // Depth
					, 0    // Stencil
					, 0    // FB texture 0, color palette 0
					, 1 == m_mode ? 1 : 0 // FB texture 1, color palette 1
				);

				bgfx::setViewClear(1
					, BGFX_CLEAR_COLOR | BGFX_CLEAR_DEPTH
					, 1.0f // Depth
					, 0    // Stencil
					, 0    // Color palette 0
				);

				bgfx::FrameBufferHandle invalid = BGFX_INVALID_HANDLE;
				bgfx::setViewFrameBuffer(0, 0 == m_mode ? invalid : m_fbh);

				// Set view and projection matrix for view 1.
				bx::mtxIdentity(view);

				const bgfx::Caps* caps = bgfx::getCaps();
				bx::mtxOrtho(proj, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 100.0f, 0.0f, caps->homogeneousDepth);
				bgfx::setViewTransform(1, view, proj);

				for (uint32_t depth = 0; depth < 3; ++depth)
				{
					uint32_t zz = m_frontToBack ? 2 - depth : depth;

					for (uint32_t yy = 0; yy < 3; ++yy)
					{
						for (uint32_t xx = 0; xx < 3; ++xx)
						{
							float color[4] = { xx * 1.0f / 3.0f, zz * 1.0f / 3.0f, yy * 1.0f / 3.0f, 0.5f };

							if (m_fadeInOut
								&& zz == 1)
							{
								color[3] = bx::sin(time * 3.0f) * 0.49f + 0.5f;
							}

							bgfx::setUniform(u_color, color);

							BX_UNUSED(time);
							float mtx[16];
							bx::mtxRotateXY(mtx, time * 0.023f + xx * 0.21f, time * 0.03f + yy * 0.37f);
							//mtxIdentity(mtx);
							mtx[12] = -2.5f + float(xx) * 2.5f;
							mtx[13] = -2.5f + float(yy) * 2.5f;
							mtx[14] = -2.5f + float(zz) * 2.5f;

							// Set transform for draw call.
							bgfx::setTransform(mtx);

							// Set vertex and index buffer.
							bgfx::setVertexBuffer(0, m_vbh);
							bgfx::setIndexBuffer(m_ibh);

							const uint64_t state = 0
								| BGFX_STATE_CULL_CW
								| BGFX_STATE_WRITE_RGB
								| BGFX_STATE_WRITE_A
								| BGFX_STATE_DEPTH_TEST_LESS
								| BGFX_STATE_MSAA
								;

							const uint64_t stateNoDepth = 0
								| BGFX_STATE_CULL_CW
								| BGFX_STATE_WRITE_RGB
								| BGFX_STATE_WRITE_A
								| BGFX_STATE_DEPTH_TEST_ALWAYS
								| BGFX_STATE_MSAA
								;

							bgfx::ProgramHandle program = BGFX_INVALID_HANDLE;
							switch (m_mode)
							{
							case 0:
								// Set vertex and fragment shaders.
								program = m_blend;

								// Set render states.
								bgfx::setState(state
									| BGFX_STATE_BLEND_ALPHA
								);
								break;

							case 1:
								// Set vertex and fragment shaders.
								program = m_wbSeparatePass;

								// Set render states.
								bgfx::setState(stateNoDepth
									| BGFX_STATE_BLEND_FUNC_SEPARATE(BGFX_STATE_BLEND_ONE, BGFX_STATE_BLEND_ONE, BGFX_STATE_BLEND_ZERO, BGFX_STATE_BLEND_INV_SRC_ALPHA)
								);
								break;

							default:
								// Set vertex and fragment shaders.
								program = m_wbPass;

								// Set render states.
								bgfx::setState(stateNoDepth
									| BGFX_STATE_BLEND_FUNC(BGFX_STATE_BLEND_ONE, BGFX_STATE_BLEND_ONE)
									| BGFX_STATE_BLEND_INDEPENDENT
									, 0
									| BGFX_STATE_BLEND_FUNC_RT_1(BGFX_STATE_BLEND_ZERO, BGFX_STATE_BLEND_SRC_COLOR)
								);
								break;
							}

							// Submit primitive for rendering to view 0.
							bgfx::submit(0, program);
						}
					}
				}
				if (0 != m_mode){
					bgfx::setTexture(0, s_texColor0, m_fbtextures[0]);
					bgfx::setTexture(1, s_texColor1, m_fbtextures[1]);
					bgfx::setState(0
						| BGFX_STATE_WRITE_RGB
						| BGFX_STATE_BLEND_FUNC(BGFX_STATE_BLEND_INV_SRC_ALPHA, BGFX_STATE_BLEND_SRC_ALPHA)
					);
					screenSpaceQuad((float)m_width, (float)m_height, s_flipV);
					bgfx::submit(1
						, 1 == m_mode ? m_wbSeparateBlit : m_wbBlit
					);
				}
			}
			// Advance to next frame. Rendering thread will be kicked to
			// process submitted rendering primitives.
			m_currFrame = bgfx::frame();
			return true;
		}
		return false;
	}

	entry::MouseState m_mouseState;

	uint32_t m_width;
	uint32_t m_height;
	uint32_t m_debug;
	uint32_t m_reset;
	bgfx::VertexBufferHandle m_vbh;
	bgfx::IndexBufferHandle  m_ibh;
	bgfx::ProgramHandle m_program;

	int64_t m_timeOffset;
	uint32_t m_currFrame;
	//01_cube
	bgfx::IndexBufferHandle m_cube_ibh[BX_COUNTOF(s_ptState)];
	int32_t m_pt;
	bool m_r;
	bool m_g;
	bool m_b;
	bool m_a;
	//05_Instancing
	bool     m_useInstancing;
	uint32_t m_lastFrameMissing;
	uint32_t m_sideSize;
	bgfx::ProgramHandle m_program_non_instanced;
#pragma region _04_Mesh
	Mesh* m_mesh;
	bgfx::UniformHandle u_time;
#pragma endregion

#pragma region _10_font
	FontManager* m_fontManager;
	TextBufferManager* m_textBufferManager;

	FontHandle m_visitor10;
	TrueTypeHandle m_fontAwesomeTtf;
	TrueTypeHandle m_fontKenneyTtf;
	FontHandle m_fontAwesome72;
	FontHandle m_fontKenney64;
	TrueTypeHandle m_visitorTtf;

	TextBufferHandle m_transientText;
	TextBufferHandle m_staticText;

	static const uint32_t numFonts = BX_COUNTOF(s_fontFilePath);

	TrueTypeHandle m_fontFiles[numFonts];
	FontHandle m_fonts[numFonts];
#pragma endregion
#pragma region _11_font_sdf
	void* m_txtFile;
	bx::StringView m_bigText;
	// Init the text rendering system.
	// FontManager* m_fontManager;
	// TextBufferManager* m_textBufferManager;
	TrueTypeHandle m_font;
	FontHandle m_fontSdf;
	FontHandle m_fontScaled;

	TextBufferHandle m_scrollableBuffer;

	TextLineMetrics m_metrics = TextLineMetrics(FontInfo());
	uint32_t m_lineCount;
	float m_visibleLineCount;
	const char* m_textBegin;
	const char* m_textEnd;

	ImVec4 m_outlineColor;
	float m_outlineWidth;
	ImVec4 m_dropShadowColor;
	float m_dropShadowOffsetX;
	float m_dropShadowOffsetY;
	float m_dropShadowSoftener;

	float m_textScroll;
	float m_textRotation;
	float m_textScale;
	float m_textSize;

	void initializeFont(uint32_t fontType)
	{
		if (m_font.idx != bgfx::kInvalidHandle)
		{
			m_fontManager->destroyTtf(m_font);
		}

		if (m_scrollableBuffer.idx != bgfx::kInvalidHandle)
		{
			m_textBufferManager->destroyTextBuffer(m_scrollableBuffer);
		}

		if (m_fontScaled.idx != bgfx::kInvalidHandle)
		{
			m_fontManager->destroyFont(m_fontScaled);
		}
		if (m_fontSdf.idx != bgfx::kInvalidHandle)
		{
			m_fontManager->destroyFont(m_fontSdf);
		}

		delete m_textBufferManager;
		delete m_fontManager;

		m_fontManager = new FontManager(512);
		m_textBufferManager = new TextBufferManager(m_fontManager);

		m_font = loadTtf(m_fontManager, "font/special_elite.ttf");

		m_fontSdf = m_fontManager->createFontByPixelSize(m_font, 0, 48, fontType, 6 + 2, 6 + 2);

		m_fontScaled = m_fontManager->createScaledFontToPixelSize(m_fontSdf, (uint32_t)m_textSize);

		if (fontType & FONT_TYPE_MASK_DISTANCE_IMAGE)
		{
			float extraScale = 2.0f;
			bimg::ImageContainer* glyphImage = imageLoad("font/glyph_space.png", bgfx::TextureFormat::Enum::BGRA8);
			m_fontManager->addGlyphBitmap(m_fontSdf, 32, (uint16_t)glyphImage->m_width, (uint16_t)glyphImage->m_height, (uint16_t)(glyphImage->m_width * 4), extraScale, (const uint8_t*)glyphImage->m_data, 0.0f, -3.0f);

			glyphImage = imageLoad("font/glyph_long.png", bgfx::TextureFormat::Enum::BGRA8);
			m_fontManager->addGlyphBitmap(m_fontSdf, 65, (uint16_t)glyphImage->m_width, (uint16_t)glyphImage->m_height, (uint16_t)(glyphImage->m_width * 4), extraScale, (const uint8_t*)glyphImage->m_data, 0.0f, -3.0f);
		}

		m_metrics = TextLineMetrics(m_fontManager->getFontInfo(m_fontScaled));
	}

	void initializeTextBuffer(uint32_t fontType)
	{
		m_scrollableBuffer = m_textBufferManager->createTextBuffer(fontType, BufferType::Transient);
	}

	void applyTextBufferAttributes()
	{
		m_textBufferManager->setTextColor(m_scrollableBuffer, 0xFFFFFFFF);
		m_textBufferManager->setOutlineColor(m_scrollableBuffer, ((uint32_t)(m_outlineColor.x * 255) << 24) | ((uint32_t)(m_outlineColor.y * 255) << 16) | ((uint32_t)(m_outlineColor.z * 255) << 8) | ((uint32_t)(m_outlineColor.w * 255)));
		m_textBufferManager->setOutlineWidth(m_scrollableBuffer, m_outlineWidth);
		m_textBufferManager->setDropShadowColor(m_scrollableBuffer, ((uint32_t)(m_dropShadowColor.x * 255) << 24) | ((uint32_t)(m_dropShadowColor.y * 255) << 16) | ((uint32_t)(m_dropShadowColor.z * 255) << 8) | ((uint32_t)(m_dropShadowColor.w * 255)));
		m_textBufferManager->setDropShadowOffset(m_scrollableBuffer, m_dropShadowOffsetX, m_dropShadowOffsetY);
		m_textBufferManager->setDropShadowSoftener(m_scrollableBuffer, m_dropShadowSoftener);
	}
#pragma endregion
#pragma region Picking
	Mesh* m_meshes[12];
	float m_meshScale[12];
	float m_idsF[12][4];
	uint32_t m_idsU[12];
	uint32_t m_highlighted;

	// Resource handles
	bgfx::ProgramHandle m_shadingProgram;
	bgfx::ProgramHandle m_idProgram;
	bgfx::UniformHandle u_tint;
	bgfx::UniformHandle u_id;
	bgfx::TextureHandle m_pickingRT;
	bgfx::TextureHandle m_pickingRTDepth;
	bgfx::TextureHandle m_blitTex;
	bgfx::FrameBufferHandle m_pickingFB;

	uint8_t m_blitData[ID_DIM * ID_DIM * 4]; // Read blit into this

	uint32_t m_reading;
	float m_fov;
	bool  m_cameraSpin;
#pragma endregion
#pragma region 29-debugdraw
	SpriteHandle   m_sprite;
	GeometryHandle m_bunny;
#pragma endregion
#pragma region 28-wireframe
	uint32_t m_oldWidth;//no use
	uint32_t m_oldHeight;//no use
	uint32_t m_oldReset;//no use

	WireFrame::Camera m_camera;
	WireFrame::Mouse m_mouse;
	WireFrame::Uniforms m_uniforms;
	WireFrame::MeshMtx m_wf_meshes[3];
	int32_t m_meshSelection;
	int32_t m_drawMode; // Holds data for 'DrawMode'.

	bgfx::ProgramHandle m_wfProgram;
	bgfx::ProgramHandle m_meshProgram;
#pragma endregion
#pragma region oit
	int32_t m_mode;
	bool m_frontToBack;
	bool m_fadeInOut;
	bool m_mrtSupported;

	bgfx::UniformHandle s_texColor0;
	bgfx::UniformHandle s_texColor1;
	bgfx::UniformHandle u_color;

	bgfx::ProgramHandle m_blend;
	bgfx::ProgramHandle m_wbSeparatePass;
	bgfx::ProgramHandle m_wbSeparateBlit;
	bgfx::ProgramHandle m_wbPass;
	bgfx::ProgramHandle m_wbBlit;

	bgfx::TextureHandle m_fbtextures[2];
	bgfx::FrameBufferHandle m_fbh;
#pragma endregion

};

} // namespace

ENTRY_IMPLEMENT_MAIN(
	  ExampleCubes
	, "01-joe-bgfx_all"
	, "Rendering all."
	, "https://bkaradzic.github.io/bgfx/examples.html#aall"
	);
